Roll20 uses cookies to improve your experience on our site. Cookies enable you to enjoy certain features, social sharing functionality, and tailor message and display ads to your interests on our site and others. They also help us understand how our site is being used. By continuing to use our site, you consent to our use of cookies. Update your cookie preferences .
×
Create a free account

text according to percentage

hello, I'm writing a character sheet and in the health section, the character has a certain status according to the health in which it is. for example If in total you have 18 health points your health is equal to = healthy. and you are in 9 points of life (50%) your state is = injured I would like to know how to write that macro so that it is reflected in the file. Thank you
1536149669

Edited 1536150036
Andreas J.
Forum Champion
Sheet Author
Translator
It would be possible to make with a sheet worker . (Roll20) macros have nothing to do with this. Here is an simple sheet worker that does the similar "if X is Y, do Z"-formula if the wiki examples aren't as helpful.
I can not get it to work, I've added the following line to my character sheet where "hp" are the points of life and "state" is the square where the "dead" effect will be reflected <script> on("state", function(eventInfo) {    getAttrs(["hp"], function(values) {         var FUE = values.FUE;         if(values.FUE == "0"){ var update = {} update.state= "dead"; setAttrs(update);}           }); }); </script>
1536158586
Andreas J.
Forum Champion
Sheet Author
Translator
I remember there being some limitations to naming things in sheet workers, try having the variable-names be lowercase. And you need to have it inside  < script type = "text/worker" >
the script with the macro of the complete character sheet is this <tr> <script type="text/worker"> on("state", function(eventInfo) {    getAttrs(["hp"], function(values) {         var FUE = values.hp;         if(values.FUE == "0"){ var update = {}; update.state = "dead"; setAttrs(update);}           }); }); </script> <td style="text-align: left; width: 33%;">PV <input name="attr_pv" type="number" />/</td> <td style="text-align: left; width: 66%;">Estado<input name="attr_state" disabled="disabled" name="attr_state" type="number" /></td> </tr>
1536163747

Edited 1536164187
Andreas J.
Forum Champion
Sheet Author
Translator
From the Sheet Worker Article : Note that the script tag must have a type of "text/worker" to be properly handled by the system. When the game loads, all script tags are removed from the sheet's template for security purposes. However, script tags with a type of "text/worker" will be used to spin up a background worker on each player's computer that can respond to changing values in their sheets and take action as needed. All sheetworker scripts need to be contained within a single script tag.  And the sheetworker script block is strongly suggested or even required to be placed at the bottom of the html sheet, like in the example I pointed out . When you say macro, what exactly are you talking about? When it comes to Roll20, it's only used to refer to Roll20 macros , nothing else.
1536168181

Edited 1536170029
GiGs
Pro
Sheet Author
API Scripter
As andreas says, put your script at the very end of the sheet. (This isnt strictly necessary, but it is much better for organisation and upgrading later, like when you add extra scripts). Your script has couple of errors in it.  The first line should probably be something like on("change:hp", function() { I'd avoid using "state" as an attribute name, since roll20 has a state object and it will lead to confusion and possibly errors. I suggest renaming state to status. Do you use hp current and maximums, or do you have a separate attribute for current hit points, and healthy, full hit points? If you need to calculate 50% of health, you need to grab both of those values in your script. If youre using a single attribute, and its current and max properties, the script should be like this (assuming you rename the state attribute to status): <script type="text/worker"> on("change:hp change:hp_max", function() {    getAttrs(["hp","hp_max"], function(values) {         let hp = parseInt(values.hp)||0;        // parseInt here makes sure the extracted value is a number let max = parseInt(values.hp_max)||0;     // "let" is a better alternative to "var", but they are basically equivalent. let status = "Healthy"         if(hp <= 0) status = "dead";            // if you only have a single statement, you dont need {} brackets else if(hp < Math.round(max/2) ) status = "Injured"; setAttrs({                            // it's best to have a single setAttrs block after setting all values.     status:status )};  }); }); </script> If you use two different stats for max and current hp, just change the references in the script as appropriate.
1536168311
GiGs
Pro
Sheet Author
API Scripter
Just a clarification on terminology: In roll20, a macro is a chat command, like /roll 2d6, that you save to a button on your character sheet or the macro tab. What we are creating here is not a macro, it's a script. There are two types of scripts in roll20: API scripts and sheet workers. We are working on a sheet worker script right now.
thanks for the support. When I referred to script it was to calculations inside the character sheet, I was wrong in the terms, I took a little time programming here and I find it hard to take the terms. Right now my sequence is like this. Although I managed to fix some details, I can not get the "dead" result to appear inside the "status" text box some suggestion? <script type="text/worker"> on("change:pv change:pv_max", function() {    getAttrs(["pv","pv_max"], function(values) {         let pv = parseInt(values.pv)||0;        // parseInt here makes sure the extracted value is a number         let max = parseInt(values.pv_max)||0;     // "let" is a better alternative to "var", but they are basically equivalent.         let status = "Healthy"         if(hp <= 0) status = "dead";            // if you only have a single statement, you dont need {} brackets         else if(hp < Math.round(max/2) ) status = "Injured";         setAttrs({                            // it's best to have a single setAttrs block after setting all values.             status:status         )};   }); }); </script> <td style="text-align: left; width: 33%; font-size:1.2em"><strong>PV</strong> <input name="attr_pv_max" disabled="disabled" type="number" value="[@{res}]" />/<input name="attr_pv" type="number" /></td> <td style="text-align: left; width: 66%; font-size:1.2em"><strong>Estado</strong> <input style="width: 200px;"name="attr_status" disabled="disabled" name="attr_status" type="text" /></td>
1536176467

Edited 1536176839
GiGs
Pro
Sheet Author
API Scripter
Change disabled to readonly. A sheet worker cannot modify a disabled input. <input style="width: 200px;"name="attr_status" type="text" readonly /> Edit: just noticed you had the name= statement twice in that input. You also switch between using pv and hp in the script. Change this line let pv = parseInt(values.pv)||0;  to let hp = parseInt(values.pv)||0;  and the rest of the script should work. You can delete the parts of lines that start // anything on a line after // is ignored by the script, it's just there as an educational comment from me to you. Also one complication: <input name="attr_pv_max" disabled="disabled" type="number" value="[@{res}]" />/<input name="attr_pv" type="number" /></td> You are setting pv_max weirdly here. If you have a @{res} stat that is used for maximum hp, you are better off using that in your script. So your script would be <script type="text/worker"> on("change:pv change:res", function() {    getAttrs(["pv","res"], function(values) {         let hp = parseInt(values.pv)||0;        // parseInt here makes sure the extracted value is a number         let max = parseInt(values.res)||0;     // "let" is a better alternative to "var", but they are basically equivalent.         let status = "Healthy"         if(hp <= 0) status = "dead";            // if you only have a single statement, you dont need {} brackets         else if(hp < Math.round(max/2) ) status = "Injured";         setAttrs({                            // it's best to have a single setAttrs block after setting all values.             status:status         )};   }); }); </script> <td style="text-align: left; width: 33%; font-size:1.2em"><strong>PV</strong> <input name="attr_res" type="number" />/<input name="attr_pv" type="number" /></td> <td style="text-align: left; width: 66%; font-size:1.2em"><strong>Estado</strong> <input style="width: 200px;"name="attr_status" type="text" readonly /></td> If you have the res attribute declared somehwere else, its fine to have it repeated here.
this is the new code and it still does not work    o_o <script type="text/worker"> on("change:hp change:hp_max", function() { getAttrs(["hp","hp_max"], function(values) { let hp = parseInt(values.hp)||0; let max = parseInt(values.hp_max)||0; let status = "Healthy" if(hp <= 0) status = "dead"; else if(hp < Math.round(max/2) ) status = "Injured"; setAttrs({ status:status )}; }); }); </script> <td style="text-align: left; width: 33%; font-size:1.2em"><strong>PV</strong> <input name="attr_hp_max" disabled="disabled" type="number" value="[@{res}]" />/<input name="attr_hp" type="number" /></td> <td style="text-align: left; width: 66%; font-size:1.2em"><strong>Estado</strong> <input style="width: 200px;"name="attr_status" name="attr_status" type="text" readonly />
1536177367
GiGs
Pro
Sheet Author
API Scripter
Did you notice I edited my last post, and put some extra code at the end? this line is probably the cause of it not working <input name="attr_hp_max" disabled="disabled" type="number" value="[@{res}]" />
it still does not work <script type="text/worker"> on("change:hp change:hp_max", function() { getAttrs(["hp","hp_max"], function(values) { let hp = parseInt(values.hp)||0; let max = parseInt(values.hp_max)||0; let status = "Healthy" if(hp <= 0) status = "dead"; else if(hp < Math.round(max/2) ) status = "Injured"; setAttrs({ status:status )}; }); }); </script> <td style="text-align: left; width: 33%; font-size:1.2em"><strong>PV</strong> <input name="attr_hp_max" type="number" />/<input name="attr_hp" type="number" /></td> <td style="text-align: left; width: 66%; font-size:1.2em"><strong>Estado</strong> <input style="width: 200px;"name="attr_status" type="text" readonly /></td>
1536180279

Edited 1536181080
Andreas J.
Forum Champion
Sheet Author
Translator
Doesn't   let status = "Healthy"    and    status:status need a semicolon at the end of the line? I have to say I don't understand how JS or almost any sheet workers work, only that I managed to get to work the example that I've pointed to previously, and it's simple enough that I understand how it works. The above example by G G flies above my head, specificly what  status:status    does 
1536180432
GiGs
Pro
Sheet Author
API Scripter
The second one is right, you shouldnt oly end that with a comma if there is a seconf entry, and no punctuation if its the only assignment. The first one should have a semi-colon, out of custom, but it will work without it. semi-colons are often optional in javascript. Some people write code without them.
1536181041

Edited 1536181309
GiGs
Pro
Sheet Author
API Scripter
You were righjt Andreas about the Healthy line, looks like that's one of the places you do need a semi-colon. Also there was a second issue - the brackets at the end of the setattrs block were the wrong way round. We expert programmers like to leave in a few deliberate typos to keep you on your toes. Honest. It was totally deliberate... ;) Here's the corrected code <td style="text-align: left; width: 33%; font-size:1.2em"><strong>PV</strong> <input name="attr_hp_max"  type="number"  />/<input name="attr_hp" type="number" /></td> <td style="text-align: left; width: 66%; font-size:1.2em"><strong>Estado</strong> <input style="width: 200px;"name="attr_status" type="text" readonly /></td> on("change:hp change:hp_max", function() {    getAttrs(["hp","hp_max"], function(values) {         let hp = parseInt(values.hp)||0;                 let max = parseInt(values.hp_max)||0;             let status = "Healthy";         if(hp <= 0) status = "Dead";                     else if(hp < Math.round(max/2) ) status = "Injured";         setAttrs({                                         status:status         });   }); }); </script>
1536181435
Andreas J.
Forum Champion
Sheet Author
Translator
Wanna tell how the  status:status line works? Does it tell to your variable named "status" to apply itself on a sheet attribute named "status"? because that's the confusing part.
ohhhh it worked. thank you very much. to see if I can finish this sheet and upload it you are some cracks
1536183508

Edited 1536183609
The Aaron
Pro
API Scripter
Andreas J.  said: Wanna tell how the  status:status line works? Does it tell to your variable named "status" to apply itself on a sheet attribute named "status"? because that's the confusing part. In a javascript object, the item to the left of the : is the name of a property, in this case "status" and the thing on the right of the : is an expression, in this case the variable status . setAttrs() takes an object whose properties are the names of attributes and values are the value to set them to. What will really blow your mind is that as of Javascript ES6, this also works: setAttrs({status}); In ES6, if you only specify a variable, it will take the name of the property from the name of the variable, and the value of the property as the value of the variable. =D
1536183845

Edited 1536184011
GiGs
Pro
Sheet Author
API Scripter
That does look confusing, but you're right. If we had an attribute on the chjaracter sheet called "health_status" and a variable tracking it called "newstatus", that line would have been health_status:newstatus The setAttrs function needs a type of variable called an object. An object is defined like this: object = {}; and it contains variables in pairs: a key and a value, which looks like this: object = {      key:value } If you have multiple items within the object, it would look like this object = {     key1:value1,     key2:value2,     key3:value3 } Notice the last item in the set doesnt have a comma or semi-colon. this data structure is handy and is used for a variety of purposes in javascript. When you have an object like this, it'll contain a bunch of values, and their keys can be used to grab them, The script above already does this with getAttrs. When using getAttrs, you get an object which contains the attributes, whose names are the keys. here, for instance:  getAttrs(["hp","hp_max"], function(values) { We are creating a values object which behind the scenes might look like this: values = {     hp: 20,     hp_max: 25 } And then we can use this line let hp = values.hp;  to get the value of hp. Its a very powerful data structure, but can take a while to wrap your head around. But once you do, its very handy because it's used everywhere in javascript. If interested, google object literals , and object data structure for more.
1536183901
GiGs
Pro
Sheet Author
API Scripter
The Aaron said: What will really blow your mind is that as of Javascript ES6, this also works: setAttrs({status}); In ES6, if you only specify a variable, it will take the name of the property from the name of the variable, and the value of the property as the value of the variable. =D Oooh, thats really handy to know. Thanks, Aaron.
1536183959
GiGs
Pro
Sheet Author
API Scripter
Kinower said: ohhhh it worked. thank you very much. to see if I can finish this sheet and upload it you are some cracks You're welcome!
1536185050
Andreas J.
Forum Champion
Sheet Author
Translator
Thanks both The Aaron and G G for the explanations, now I understand it much better. It took me some time to understand The Aaron 's explanation (that indirectly answered my question), and did so just as G G 's answers was posted the question,  which clearly and directly in the first two rows answers my question, following up with further explanations of the underlying principles. I'll do more reading on JS before I'll do sheet workers, as it's mostly looks like witchcraft to me, with only small snippets of understandable things I recognize from C and Python.
1536187394

Edited 1536187883
GiGs
Pro
Sheet Author
API Scripter
You really don't need to understand how sheet workers work, to be honest. As long as you copy the change / get attrs / setattrs sections properly, to get the data you operate on with fairly standard programming techniques. Here's a simple template on("change:stat1 change:stat2 sheet:opened", function() { //sheet:opened is optional, but is useful for some workers - the script runs every time the sheet opens.    getAttrs(["stat1","stat2"], function(values) {         let stat1 = values.stat1;                // wrap this in a parseInt function if you need it to be a number         let stat2 = parseInt(values.stat2)||0;    // like so // ============================ // at this point you have the variables you need to work with. Do whatever you need below, using ifs, switches, for loops, and so on // as you would in other programming languages. You can use very simple stuff, similar to BASIC programming, whatever suits your level of skill. // then once you have done whatever stuff you need to do to get your desired output: // the bit below the line lets you wrap up the sheet worker. // ============================         setAttrs({                                         stat1:stat1,             stat2:stat2         });   }); }); If you have different, more, or less stats, you just need to add them to the change, getattrs, and setattrs lines, and the variable assignments. You really dont need to understand how they work, as long as you can copy them and update them with correct values. Then you can do what you need with them between the double lines. I hope this helps. In the beginning I was just as befuddled about them as you are, and using a template like this got me started. Two tips I'd suggest when starting out: keep your attribute names lower case Don't use dashes or other symbols except underscores in attribute names  So if you have a name like Health-Value, change it to health_value. You can break these guidelines when you know what you're doing, but you need to write the sheet workers slightly differently, and it's better to avoid the hassle when starting out.
1536188870
vÍnce
Pro
Sheet Author
@GG Thanks for posting a template to follow.  I wish the wiki had this as well as a few other commonly needed templates for us non-programmers.  The few examples given seem geared more toward people with programming experience.
1536189131

Edited 1536189425
GiGs
Pro
Sheet Author
API Scripter
Andreas, you linked a sheet worker earlier in the thread. I thought it would be instructional to show how to convert that worker to this template format, especially since that worker could be optimised quite a bit. Here's the original sheet worker you linked, which looks quite different to the format I suggested: on("change:force_emptiness change:darksidepoints", function() {    getAttrs(["Force_EmptinessMod", "Force_Emptiness","darkSidePoints"], function(values) { if(values.Force_Emptiness == "false"){ var update = {}; update.Force_EmptinessMod = "0"; setAttrs(update); } if(values.Force_Emptiness == "true"){ if(values.darkSidePoints == "0"){ var update = {}; update.Force_EmptinessMod = "6"; setAttrs(update); } if(values.darkSidePoints == "1"){ var update = {}; update.Force_EmptinessMod = "5"; setAttrs(update); } if(values.darkSidePoints == "2"){ var update = {}; update.Force_EmptinessMod = "4"; setAttrs(update); } if(values.darkSidePoints == "3"){ var update = {}; update.Force_EmptinessMod = "3"; setAttrs(update); } if(values.darkSidePoints == "4"){ var update = {}; update.Force_EmptinessMod = "2"; setAttrs(update); } if(values.darkSidePoints == "5"){ var update = {}; update.Force_EmptinessMod = "1"; setAttrs(update); } if(values.darkSidePoints == "6"){ var update = {}; update.Force_EmptinessMod = "0"; setAttrs(update); } }    }); }); This code includes a lot of redundancy, and here's one way of rewriting it: on("change:force_emptiness change:darksidepoints", function() {    getAttrs(["Force_Emptiness","darkSidePoints"], function(values) { let Force_Emptiness = values.Force_Emptiness; let Force_EmptinessMod = 0; let darkSidePoints = parseInt(values.darkSidePoints)||0; if(Force_Emptiness == "true") Force_EmptinessMod = 6 - darkSidePoints; setAttrs({ Force_EmptinessMod:Force_EmptinessMod });    }); }); Notice how much shorter that is? I use the templated to fill in the beginning and ending, then I look at the structure of the code and noticed that forceemptinessmod and darksidepoints always added up to 6, and forcemptiness_mod always equalled 0 when force_emptiness was false. So I could reduce the entire structure to a single if statement. The vast majority of things you use sheet workers for will be simple things like this, and having a format for the beginning and ending means you can handle the actual meat of the script - the thing its actually for - pretty easily, usually.  Experienced folk will be able to simplify this even further, removing several steps (like skipping assigning the variables), but sticking to this method means you have less to struggle with and can concentrate on the bits you need to do, the heart of the sheet worker.
1536191456
Andreas J.
Forum Champion
Sheet Author
Translator
As long as you copy the change / get attrs / setattrs sections properly, to get the data you operate on with fairly standard programming techniques. Yeah, that's how I ended up with the above code. You really don't need to understand how sheet workers work, to be honest. Here's a simple template: I really have to say that it's a horrible practice to use same name for different variables, especially if the point is to illustrate how something simple worth while saying that you really dont need to know how it works. The status:status  really threw me off, as I wasn't as familiar with JS and how things interact. I assume you still expect people to understand JS in some way, because things like that will throw off other than just me.  Just my two cents.   G G said: Andreas, you linked a sheet worker earlier in the thread. I thought it would be instructional to show how to convert that worker to this template format, especially since that worker could be optimised quite a bit. Hot damn, that is quite some simplification, thank you so many times over! I didn't understand much anything so that is the result of looking at different sheet and slapped together something working, no thanks to the examples on the wiki. Your examples and explanations did better work of understanding sheet workers than several hours spent on reading the wiki page, skimming JS basics and looking at other's code ever did. Could you take a quick look at the sheetworker wiki article and/or add your example there? Everything beyond the first comment in this thread stems from the article being less than illuminating with it's examples. PS: I'll also take your beautiful piece of rewritten code and replace the original :D
1536193429
GiGs
Pro
Sheet Author
API Scripter
If I was to add that template to the wiki, where would i put it? i havent added to the wiki before. Vince said: @GG Thanks for posting a template to follow.  I wish the wiki had this as well as a few other commonly needed templates for us non-programmers.  The few examples given seem geared more toward people with programming experience. Andreas J. said: Could you take a quick look at the sheetworker wiki article and/or add your example there? Everything beyond the first comment in this thread stems from the article being less than illuminating with it's examples. PS: I'll also take your beautiful piece of rewritten code and replace the original :D I didn't realise that was your code, I'm glad you can use it too :) I agree completely with you and Vince's comments about the wiki. I often find it frustratingly dense, and have complained that it's written by programmers for programmers. My personal dream wiki would be instead of having, say, a huge collection of objects on one page, events on another page, would instead have a separate page for every single object, and every single event, and every single function, with examples of each in use - and the current single page monstrosities would simply serve as summary and index pages for them. But that would be a LOT of time and work, and everyone contributing is a volunteer, so I am grateful for what we've got, even if it makes me pull my hair out at times, hehe. Andreas, I do agree it's a bit confusing using the same variable names as the stat names. I was going off the idea that people using the template would just ignore the start and end as much as possible, and didnt want to have to explain the differences between general variables and object keys. Aaron also points out an advantage to it that, in that you can simplify setAttrs({ Force_EmptinessMod:Force_EmptinessMod }); to setAttrs({Force_EmptinessMod}); if you do do it that way, which I wasn't aware of. But you dont need to use the same variable and attribute names, and if it's clearer for you to keep them distinct, you should do that.
1536193550
GiGs
Pro
Sheet Author
API Scripter
The Aaron said: What will really blow your mind is that as of Javascript ES6, this also works: setAttrs({status}); In ES6, if you only specify a variable, it will take the name of the property from the name of the variable, and the value of the property as the value of the variable. =D Aaron, when you have multiple attributes, would separating them with a comma still work normally? Like, if I had this: setAttrs({                                         stat1:stat1,             stat2:stat2         }); would that simplify to setAttrs({                                         stat1,             stat2         });
1536196695
vÍnce
Pro
Sheet Author
G G said: If I was to add that template to the wiki, where would i put it? i havent added to the wiki before. Here:&nbsp; <a href="https://wiki.roll20.net/Sheetworker_examples_for_Non-programmers" rel="nofollow">https://wiki.roll20.net/Sheetworker_examples_for_Non-programmers</a> ;-P Feel free to add to, edit, whatever.
1536199990
GiGs
Pro
Sheet Author
API Scripter
Wow, I'm fast!
1536202515
The Aaron
Pro
API Scripter
G G said: The Aaron said: What will really blow your mind is that as of Javascript ES6, this also works: setAttrs({status}); In ES6, if you only specify a variable, it will take the name of the property from the name of the variable, and the value of the property as the value of the variable. =D Aaron, when you have multiple attributes, would separating them with a comma still work normally? Like, if I had this: setAttrs({&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; stat1:stat1, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stat2:stat2 &nbsp; &nbsp; &nbsp; &nbsp; }); would that simplify to setAttrs({&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; stat1, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stat2 &nbsp; &nbsp; &nbsp; &nbsp; }); Absolutely. Something else you might find handy is using an expression for a property: setAttrs({&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [attrname+"_max"]: 10 &nbsp; &nbsp; &nbsp; &nbsp; });
1536204126

Edited 1536204138
GiGs
Pro
Sheet Author
API Scripter
Thanks! I knew about the expression thing, it's handy, but was keeping the template simple. That's why I suggested avoiding symbols like dashes in attribute names, so that approach didnt need to be explained. If I update the template page on the wiki, I'll include a footnote about handling that, and the pitfalls of upper case vs lowercase for change events, etc.
at the end my code remained,&nbsp;and it works perfectly &lt;tr&gt; &lt;script type="text/worker"&gt; on("change:hp change:hp_max", function() { getAttrs(["hp","hp_max"], function(values) { let hp = parseInt(values.hp)||0; let max = parseInt(values.hp_max)||0; let status = "SANO"; if(hp &lt; Math.round((max/2)+1)) status = "HERIDO. movimiento 1/2"; if(hp &lt; Math.round((max/4)+1)) status = "MALHERIDO. Resx4/turno o inconsciente, mov 1/4"; if(hp &lt;= 0) status = "INCONSCIENTE. -1 PV, cada turno hasta sanar"; if(hp &lt; Math.round(-max+1) ) status = "MUERTO!!!"; setAttrs({ status:status }); }); }); &lt;/script&gt; &lt;td style="text-align: left; font-size:1.2em"&gt;&lt;strong&gt;Puntos de Vida&lt;/strong&gt; &lt;input style="width: 50px;" name="attr_hp_max" type="number" /&gt;/&lt;input style="width: 50px;" name="attr_hp" type="number" /&gt;&lt;/td&gt; &lt;td style="text-align: left; font-size:1.2em"&gt;&lt;strong&gt;Estado&lt;/strong&gt; &lt;input style="width: 330px;" name="attr_status" type="text" readonly /&gt;&lt;/td&gt; &lt;/tr&gt;