Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Updating variables?

I'm using Twine 2.0.11 and Sugarcube 2.12.0

I'm using a rpg system and some of my variables (player HP, etc.) isn't updating - I use the display macro to show the stats in multiple passages. When I switch to a new passage it goes back to the old variable and ignores the most recent passage I used.

Is there a macro available just to update the specific variables? Thank you!

Comments

  • First. What you've described doesn't say much about what you're actually doing, so you're going to have to get into more detail than that. Preferable with code examples—use the code tag, C on the editor bar.

    Beyond that. The <<set>> macro is what you should, generally, be using to modify the values of variables.

    Question. Are you using <<back>> in any of these passages by any chance?
  • edited December 2016
    Ah, my apologies. it's a little difficult to post the codes because I'm not sure where to start. Basically: I have three passages: one that explores a map, one more that starts a battle, and another town passage (this is further broken up into two separate passages - a text log and command actions - that are both displayed under a third one). I have player stats displayed in both the map and the battle passages using the display code.

    I tested my rpg by intentionally losing a battle, bringing my health down to 1 hp. I then go to the town and sleep to replenish my HP, and then go out to the map to battle again. When I explore the map, my health accurately displays the latest stat, but when I enter into battle, my health reverts back to the 1 hp I had before I entered the town. So as you can see, it's encompassing quite a few passages so I'm not exactly sure which codes are the problem.

    Playerturn passage (battle):
    <center><div class="battleattack">
    <<set $location to "PlayerTurn">>
    <<set $elementarmor to 0>>
    
    <<if $CastAccessoryHeal eq "yes">>
    	<<set $CastAccessoryHeal to "no">>
    	You have healed $playerHPcast HP!
    <</if>>
    
    <<if $armor.element eq $monsters.element>>
    	<<set $elementarmor to $elementarmor + $armor.elementadd>>
    <</if>>
    
    <<if $headgear.element eq $monsters.element>>
    	<<set $elementarmor to $elementarmor + $headgear.elementadd>>
    <</if>>
    
    <<if $shield.element eq $monsters.element>>
    	<<set $elementarmor to $elementarmor + $shield.elementadd>>
    <</if>>
    
    <<if $turn eq "enemy">>
    /% For more comments, see "Attack" passage. %/
    
    <<if $monsterispoisoned eq 1>>
    <<set $poisonRoll to Math.floor((Math.random()*100)+1)>>
    	<<if $poisonRoll lte $monsters.poisonchance>>
    		<<set $monsterispoisoned = 1>> 
    	<</if>>
    <<set $poisondamage = Math.floor(5 + $perkwisdom + $player.wisdom/10)>> 
    <<set $monsters.HP to $monsters.HP - $poisondamage>>
    Monster is poisoned and takes $poisondamage damage!<br><br>
    <</if>>
    
    <<print $monsters.name>> attacks!<br><br>
    
    <<set $attackRoll = Math.floor((Math.random()*20)+1)>>
    
    <<if ($monsters.attack + $attackRoll) gte ($player.AC + $shield.AC)>>
    
    It hits!<br><br>
    
    <<if $monsters.poisonchance gt 0 and $poisoned eq 0 and $damage gt 0>>
    	<<set $poisonRoll = Math.floor((Math.random()*100)+1)>>
    		<<if $poisonRoll lte $monsters.poisonchance>>
    			<<set $poisoned = 1>>
    			You've been poisoned!<br><br>
    			<<set $monsterPoison = $monsters.poison>>
    		<<endif>>
    <</if>>
    
    <<set $damageRoll = Math.floor(Math.random()*(8-4+1)+4)>> 
    <<set $damage = ($monsters.damage + $damageRoll) - ($armor.AC + $shield.AC + $headgear.AC + $accessory.AC + $elementarmor)>>
    
    <<if $damage lt 0>><<set $damage = 0>><<endif>>
    
    You take <<print $damage>> damage!<br><br>
    
    <<set $player.HP = $player.HP - $damage>>
    
    You have <<print $player.HP>> HP left!<br><br>
    
    <<if $player.HP lte 0>>
    
    <span class="actions">
    	<<link "You lost!">>
    		<<set $battle to "lose">>
    		<<set $monsterboss to "no">>
    		<<set $player.HP to 1>>
    		<<print "<<goto \"" + $monsters.name + "Win\">>">>
    	<</link>>
    </span>
    <</if>>
    
    <<else>>
    
    It misses!<br><br>
    
    /% End $monster.attacks counter %/
    
    <</if>>
    
    <</if>>
    </div>
    
    <<if $player.HP gt 0>>
    
    <<if $poisoned eq 1>>
    <<set $playerarmor = $armor.AC + $headgear.AC + $shield.AC + $accessory.AC>>
    <<set $poisonDamage = Math.floor($player.maxHP * $monsterPoison) + Math.floor((Math.random()*3)+1)>>
    <<set $player.HP = $player.HP - $poisonDamage>>
    
    <<if $player.HP lte 0>>
    <<set $player.HP = 1>>
    <</if>>
    
    <<set $sexlog to "Damage from poison.">> 
    
    <</if>>
    
    <span class="actions">
    	<<link "Attack">>
    	<<set $AttackPower to 1>>
    	<<set $turn to "enemy">>
    	<<set $sexlog to "Attack">>
    	<<goto "PlayerAttack">>
    	<</link>>
    </span>
    
    <span class="actions">
    	<<link "Cast a Spell">>
    	<<set $AttackPower to 1>>
    	<<goto "PlayerSpell">>
    	<</link>>
    </span>
    
    <span class="actions">
    	<<link "Use Items">>
    	<<goto "PlayerItems">>
    	<</link>>
    </span>
    
    <span class="actions">
    	<<link "Seduce">>
    	<<goto "PlayerSeduce">>
    	<</link>>
    </span>
    
    <span class="actions">
    	<<link "Run away!">>
    	<<goto "RunAway">>
    	<</link>>
    </span>
    <</if>>
    </center>
    
    <<display "PlayerStatistics">>
    
    

    MapThessila passage (map):
    <<set $location to "MapThessila">>
    <<set $MapThessilaArray to
    [[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,1,0,0,0,0,0,1,1,1,0,4,0,0,0,0],
    [0,1,0,0,0,0,0,1,0,1,1,1,1,1,1,0],
    [0,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0],
    [0,1,1,1,1,0,0,1,1,1,1,1,0,0,0,0],
    [0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,0],
    [0,0,0,0,1,0,0,1,1,0,0,1,1,1,0,0],
    [0,3,0,0,1,0,0,1,1,1,0,0,0,1,0,0],
    [0,1,0,0,1,0,0,1,2,1,1,0,0,1,0,0],
    [0,1,0,0,1,0,0,1,1,1,1,0,0,1,0,0],
    [0,1,0,0,1,0,0,0,1,0,1,0,0,1,0,0],
    [0,1,1,1,1,1,1,1,1,0,1,1,1,1,0,0],
    [0,1,0,0,0,1,0,0,0,0,1,0,1,0,0,0],
    [0,1,0,0,0,1,0,0,0,0,1,0,1,0,0,0],
    [0,1,0,0,0,1,0,0,0,0,1,1,1,1,5,0],
    [0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]]>>
    
    <<display "MapSystemThessila">>
    <<display "PlayerStatistics">>
    

    The town passage code (TownThessila passage) is pretty long, but here's the code for the action button where the HP should have been replenished. It works, but this disappears when I go out of town and get into a battle scene.
    	<span class="actions">
    		<<link "Rest for 50 coins.">>
    		<<set $rest to "yes">>
    		<<set $sexlog to "Rest for 50 coins.">>
    		<<set $player.HP to $player.maxHP>>
    		<<set $playerMP to $player.maxMP>>
    		<<set $player.coins to $player.coins - 50>>
    		<<goto "TownThessila2">>
    		<</link>>
    	</span>
    

    PlayerStatistics passage:
    <div id="right-ui-bar">
    $player.name<br>
    Level $player.level<br>
    $player.alignment alignment<br><br>
    HP: $player.HP / $player.maxHP<br>
    MP: $player.MP / $player.maxMP<br>
    Attack: $totalattack <br>
    Damage: $totaldamage<br>
    Armor: $totalarmor<br>
    Coins: $player.coins<br>
    XP: $player.XP<br><br><span style="list-style:none; width:100%;"><<print "<li style='background:#D0BE3F; width: " + $player.strength/4 + "%;' >strength</li><br>">><<print "<li style='background:#D0BE3F; width: " + $player.wisdom + "%;' >wisdom</li><br>">><<print "<li style='background:#D0BE3F; width: " + $player.stamina/4 + "%;' >stamina</li><br>">><<print "<li style='background:#D0BE3F; width: " + $player.seduction/4 + "%;' >seduction</li><br>">><<print "<li style='background:#D0BE3F; width: " + $player.wealth/10 + "%;' >wealth</li>">>
    </span>
    </div>
    

    Basically, I go through the passages in this order: Battle -> 1 HP -> move around Map -> go to Town -> replenish HP -> go back to map -> go to battle

    Everything works right up until I enter battle and I'm back to the 1 hp.

    If you need more info, I do have an online version of the game up (http://www.philome.la/PaperWaifu/godhood), but it is 1.) text-based but still absolutely NSFW, and 2.) might take playing a bit further along to get to the bug. I also have a saved game I can send, but I have no idea how to transfer saved games to someone else.

  • @Coraline A couple of things:

    1. Your town passage code has a variable name error:
    <<set $playerMP to $player.maxMP>>
    
    should be
    
    <<set $player.MP to $player.maxMP>>
    

    2. Your Playerturn passage (battle) passage uses a number of variables like $poisoned to determine what happens in the battle but you did not include any information about where those types of variables get reset to default values before the battle starts the second time around. If they are not getting reset then that could effect the second battle.
  • edited December 2016
    1. Thanks, missed that!

    2. When the player clicks on the Attack button in the PlayerTurn passage, it goes to a "Playerattack" passage, which then goes to a "DeathCheck" passage which checks the status of the battle and reset variables if the monster is at 0 hp and slain (set poisoned to 0, etc.).

    Here's the PlayerAttack passage:
    <center><div class="battleattack">
    <<set $elementdamage to 0>>
    
    You attack!<br><br>
    
    /% If $attackRoll + $player.attack is greater than or equal to 
    $monsters.AC ("armor class"), the attack hits. %/
    
    <<set $attackRoll = Math.floor((Math.random()*20)+1)>>
    
    <<if ($weapon.attack + $player.strength + $perkstrength + $attackRoll) gte $monsters.AC>>
    
    You hit!<br><br>
    
    <<if $weapon.element eq $monsters.element>>
    	<<set $elementdamage to $elementdamage + $weapon.elementadd>>
    <</if>>
    
    <<set $damageRoll = Math.floor(Math.random()*(8-4+1)+4)>> /% Generates 8-4 %/
    <<set $damage = Math.floor(($player.strength + $perkstrength + $weapon.damage + $elementdamage + $damageRoll) * $AttackPower) - $monsters.AC>>
    <<if $damage lt 0>><<set $damage = 0>><<endif>>
    
    <<print $monsters.name>> takes <<print $damage>> damage!<br><br>
    
    <<set $monsters.HP = $monsters.HP - $damage>>
    
    <<print $monsters.name>> has <<print $monsters.HP>> HP!<br><br>
    
    <<display "DeathCheck">> /% Is monster dead? %/
    
    <<else>> /% The attack was NOT gte $monsters.AC. %/
    
    You miss!<br><br>
    
    <</if>> /% End of the whole entire Attack conditional branch. %/
    
    /% The following *always* runs on attack, even if monster is dead (so only display stuff on the condition monster is alive): %/
    
    <<if $castAccessoryHeal is "yes">>
    	You cast the $accessory.spell!<br>
    	You gained $accessory.heal HP!<br>
    	You now have <<print $player.HP>> HP!<br><br>
    <</if>>
    
    <<if $monsters.HP gt 0>> /% Only when monster is alive, show these options . . . %/
    	<span class="actions">
    		<<link "Next Turn">>
    			<<goto "PlayerTurn">>
    		<</link>>
    	</span>	
    <</if>>
    </div></center>
    
    <<display "PlayerStatistics">>
    

    And here's the DeathCheck passage:
    <<if $monsters.HP lte 0>> /% If monster is dead. . . %/
    <<set $battle to "win">>
    <<print $monsters.name>> has lost!<br>
    <<set $monsterboss to "no">>
    
    <<set $player.XP = $player.XP + $monsters.XP>>
    <<set $randomGold = Math.floor((Math.random()*9)+1)>>
    <<set $player.coins = $player.coins + $monsters.coins + Math.floor($perkwealth/4 + $player.wealth/4) + $randomGold>>
    <<set $poisoned to 0>>
    
    You receive <<print $monsters.XP>>XP!<br>
    You receive <<print $monsters.coins + $randomGold + Math.floor($perkwealth/4 + $player.wealth/4)>>coins!<br><br>
    
    <<display "Level Up">> /% Check to see if player levels up. %/
    
    <span class="actions">
    	<<link "Continue">>
    		<<print "<<goto \"" + $monsters.name + "Win\">>">>
    	<</link>>
    </span>
    <</if>>
    

    (Like I said, there were a lot of passages, and didn't know which ones were affecting it. Was hoping if there was some kind of update macro to sort of force the variable to update, or will something like that not work with my current setup?)
  • Oh, and for Madexile:

    I'm not using any back macros for this.
  • Coraline wrote: »
    Was hoping if there was some kind of update macro to sort of force the variable to update...
    As stated by TheMadExile the <<set>> macro changes the value of a variable in the current passage.

    When the story traverses (forward) from one passage to the next (the next passage can also be the same as the last one) the current state of all known variables is persisted in the History system. So if you are using <<set>> on a non-temporary variable then you are already using a macro that "force the variable to update"
  • edited December 2016
    That's odd, then - I did use the <<set>> macro in the town passage to update it. But when i move to a battle, it reverts to the value I had BEFORE I entered the town, - even though it was displaying the correct values up until that point. The value error happens during the transition from map to battle. I've been looking through my PlayerTurn passage again trying to see if I'd set the HP variable there any differently, but no dice.
  • Is it possible the damage logic in the battle related passages are being triggered to cause the HP to return to 1?
    I don't have time ATM to debug the version you linked, I will try to do that later today but maybe TME may do it before then.
  • Nothing jumps out at me. Are you modifying or copying the $player variable directly anywhere or just modifying the properties of the object it contains? If you're doing the former anywhere, that may be where the issue lies.

    Beyond that, is the following code supposed to modify $player.HP? It looks like that was the intent, but it never obviously modifies the player's hit points.
    <<if $castAccessoryHeal is "yes">>
    	You cast the $accessory.spell!<br>
    	You gained $accessory.heal HP!<br>
    	You now have <<print $player.HP>> HP!<br><br>
    <</if>>
    
  • edited December 2016
    greyelf wrote: »
    Is it possible the damage logic in the battle related passages are being triggered to cause the HP to return to 1?
    I don't have time ATM to debug the version you linked, I will try to do that later today but maybe TME may do it before then.

    There's none that I could see, because the HP already reverts to 1 HP before I do anything in the battle. Entering the battle itself triggers the 1 HP, and not by doing any actions within the passage.

    Here's the part of one other passage that's displayed in the one of passages linking to the Map passage that leads to the battle scene upon encountering a monster, to decide if you'll fight or run away:
    	<span class="actions">
    		<<link "Fight!">>
    		<<set $turn to "player">>
    		<<goto "PlayerTurn">>
    		<</link>>
    	</span>
    	<span class="actions">
    		<<link "Run away!">>
    		<<goto "RunAway">>
    		<</link>>
    	</span>
    
    Nothing jumps out at me. Are you modifying or copying the $player variable directly anywhere or just modifying the properties of the object it contains? If you're doing the former anywhere, that may be where the issue lies.

    The only thing I can think of is my putting <<display "PlayerStatistics">> in the map and in the battle passages. I haven't modified $player anywhere else and in any other way that I know of beyond the examples I put here. But $player is also an array, though. From my StoryInit:

    <<set $player = {
    	name: "Caelas",
    	god: "none",
    	gender: "male",
    	skin: "none",
    	hair: "none",
    	eye: "none",
    	build: "none",
    	features: "none",
    	alignment: "no",
    	alignmentnumber: 0, 
    	strength: 1,
    	wisdom: 5,
    	stamina: 5,
    	seduction: 1,
    	wealth: 1,
    	skill: [],
    	maxHP: 150,
    	HP: 150,
    	maxMP: 10,
    	MP: 10,
    	AC: 6,
    	attack: 10,
    	damage: 1,
    	speed: 10,
    	coins: 200,
    	XP: 0,
    	levelUp: 100,
    	level: 1,
    }>>
    
    
    Beyond that, is the following code supposed to modify $player.HP? It looks like that was the intent, but it never obviously modifies the player's hit points.
    <<if $castAccessoryHeal is "yes">>
    	You cast the $accessory.spell!<br>
    	You gained $accessory.heal HP!<br>
    	You now have <<print $player.HP>> HP!<br><br>
    <</if>>
    

    Ah, this one will be triggered by one of the action commands in PlayerTurn, if you choose Spells to attack. That leads to a PlayerSpells passage where selecting "Heal" will set $castaccessoryheal to yes and then goes back to the PlayerTurn passage.

    Hehe, I split the battle passage into several smaller ones hoping to make it easier to code, but it looks like it's a lot harder to debug this way!
  • So what happens if you battle yourself down to, say, 5HP and then try the scenario? Is the problem you're getting your old HPs back or that your HPs are being set to 1?

    Try adding some <<print "Point xxx: " +$player.HP >> statements throughout your playerTurn passage to see if you can isolate where the HPs are being changed (change the value of xxx on each one). Put the first one on the very first line so you don't waste a lot of time if the value has already been changed by the time you get there.

    Got anything in your PassageEntry passage?
  • edited December 2016
    Ohhhhh! I tried it, and I only get the error when my HP gets lower than 0, but not when my HP is at least 1 HP.

    I checked back on some of the passages when I'm battling bosses, and saw that I made a <<set $player.HP to 1>> if I lose to a boss. When I added in an if condition:
    <<if $player.HP lte 0>>
          <<set $player.HP to 1>>
    <</if>>
    

    and then tested it out, it looks like finally worked! Values are being updated properly this time around. So it really was another code I added in that I hadn't even put in here that was causing the error. Ugghhh. I don't completely understand why adding the if condition would make the difference, but right now I'm just really glad it's working cause this was something I've been trying to figure out for 4 days now.

    Thank you, thank you, thank you so much! :)
Sign In or Register to comment.