Howdy, Stranger!

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

Going back to the room after the combat

So I got a bit stuck because of my limited knowledge of both SugarCube and JavaScript. I manage to create a dungeon with 20 seperate passages (rooms) and added a custom macro that puts you randomly in one of those passages each time you move through the door. I've also created a basic turn based combat system using few different passages for player turn/enemy turn, using magic, items and death. The way it works is that there's a set chance for enemy to appear each time player enters a new random room and then he's moved to combat passages.

Now, the problem I have. When the battle ends (with player still alive) the player should be moved back to the exact same room he got attacked. For example, he enters the dungeon and custom macro puts him in the room 9. Then he moves through the door and, again, custom macro puts him in, let's say, room 14 where he gets attacked. He's moved to the combat passages. He defeats his enemy and after the firght he should be moved back to the exact same room, which in this case is room 14. Problem is that the fight can start in each one of those 20 rooms and I want the player to always get back to the same room he got attacked in.

Is there any way, through maybe somehow saving the passage where the fight starts, to set it in a way that will always move the player to the same room he got attacked in?

I'd appreciate any kind of help. :)

Comments

  • You could do it in a number of different ways. Have your macro store the passage in a variable, have the door do it, have the combat passage do it, etc.

    You haven't exactly given a lot of details about how all of these things tie together, so I'm going to guess that the simplest is to have the macro do it, assuming the macro is actually playing the next room passage and that you do not call it within the combat passage(s).

    Try something like the following in your macro, before you play the next passage:
    State.variables.lastPassage = State.passage;
    
    Then you'd simply reference $lastPassage in your combat passage(s) to return the player to the last passage they were in. For example:
    [[Now that combat is over, you return to what you were doing.|$lastPassage]]
    
  • I added first line of code to my macro and the passage link to end combat passage and it works perfectly. Thank you kindly for that. It looks pretty simple but it was a huge pain for me. :/

    Might as well use this thread to ask one more question. :)

    I'll try to be more specific this time.

    My test macro for attack during exploration looks like this:
    macros.mAttack = {
    	"handler" : function(place, macroName, params, parser) {
    		var mAttack = Math.floor((Math.random()*100)+1);
    		if (mAttack >= 1&&mAttack <= 40) {
    			new Wikifier(place, "<<encounter>>");
    		}
    		if (mAttack >= 41&&mAttack <= 100) {
    			new Wikifier(place, "However, you find no monsters to slay.<br /><br />Continue [[exploring|Explore]]<br /><br />Return to [[town|Combat Test Town]]<br /><br />");
    		}
    	}
    }
    

    Now, what I want to do is when player gets back from combat passage to the room where he was attacked (thanks to your line of code), mAttack macro wont activate. So basically I don't want player to be attacked again right after exiting the combat menu, though the macro should activate if the player will leave this rooms and revisit it later on.
  • Feren wrote: »
    My test macro for attack during exploration looks like this: […]
    First. Nitpicks:
    1. Why aren't you using the random() function?
    2. Your if statements are less than stellar.
    3. You're not terminating your assignment to macros.mAttack.
    I'm going to make a suggestion here:
    macros.mAttack = {
    	handler : function (place, macroName, params, parser) {
    		var
    			eventRoll = random(1, 100),
    			what;
    
    		if (eventRoll <= 40) {
    			what = "<<encounter>>";
    		}
    		else {
    			what = "However, you find no monsters to slay.\n\nContinue [[exploring|Explore]]\n\nReturn to [[town|Combat Test Town]]\n\n";
    		}
    
    		new Wikifier(place, what);
    	}
    };
    
    I don't have the energy to complain about legacy macros vs. SugarCube's Macro API.

    Feren wrote: »
    Now, what I want to do is when player gets back from combat passage to the room where he was attacked (thanks to your line of code), mAttack macro wont activate. So basically I don't want player to be attacked again right after exiting the combat menu, though the macro should activate if the player will leave this rooms and revisit it later on.
    There are several ways to do it, however, the easist would likely be to have the "door" passage unset $lastPassage and to check its value within the macro—i.e. if it has no value, then the player should be coming from the "door" passage, elsewise the player should be coming back from combat.

    For example, do something like the following near the top of your "door" passage:
    <<unset $lastPassage>>
    
    And your updated mAttack macro:
    macros.mAttack = {
    	handler : function (place, macroName, params, parser) {
    		var
    			// Has the player fought?
    			hasFought = !!State.variables.lastPassage,
    
    			// Event roll (1–100).
    			eventRoll = random(1, 100),
    
    			// What happens.
    			what;
    
    		if (!hasFought && eventRoll <= 40) {
    			what = "<<encounter>>";
    		}
    		else {
    			what = "However, you find no monsters to slay.\n\nContinue [[exploring|Explore]]\n\nReturn to [[town|Combat Test Town]]\n\n";
    		}
    
    		new Wikifier(place, what);
    	}
    };
    
    Though, if we assume that 100 will always be "nothing happens", then I might write that instead as:
    macros.mAttack = {
    	handler : function (place, macroName, params, parser) {
    		var
    			// Has the player fought?
    			hasFought = !!State.variables.lastPassage,
    
    			// Event roll (1–100), short circuited if the player has already fought.
    			eventRoll = hasFought ? 100 : random(1, 100),
    
    			// What happens.
    			what;
    
    		if (eventRoll <= 40) {
    			what = "<<encounter>>";
    		}
    		else {
    			what = "However, you find no monsters to slay.\n\nContinue [[exploring|Explore]]\n\nReturn to [[town|Combat Test Town]]\n\n";
    		}
    
    		new Wikifier(place, what);
    	}
    };
    


    PS: Of course, one might wonder why you're even using a macro when standard markup would suffice—again assuming that 100 is "nothing happens".
    <<set _eventRoll to !!$lastPassage ? 100 : random(1, 100)>>\
    <<if _eventRoll lte 40>>\
    <<encounter>>\
    <<else>>\
    However, you find no monsters to slay.
    
    Continue [[exploring|Explore]]
    
    Return to [[town|Combat Test Town]]
    
    <</if>>
    
  • edited October 2016
    1. I tried using it but I always got an error when I tried to run it second time (probably did it wrong), so I changed it to how it is right now.
    2. I guessed as much. Sorry for that, but I just started learning both Twine/SugarCube and JavaScript so most of it is bound to look terrible. At least for now.
    3. I'm lost here. How should I do that?

    As for the <<unset $lastPassage>> I guess I messed something up but I get an error while I try to get back to the room after the fight. It's telling me that the passage "$lastPassage" does not exists. Where should I exactly place the <<unset $lastPassage>>? In each one of the random rooms?

    I decided to use macro to train a bit with JavaScript and also so I wouldn't have to place that markup in every random room passage. Maybe not the most practical way but it's fun to make a working custom macro. :P

    Also, excuse me the long time it took me to write an answer. I literally had no time during the last week to even open up Twine :/

    Thanks again for your help.
  • Feren wrote: »
    Where should I exactly place the <<unset $lastPassage>>? In each one of the random rooms?
    As I stated in my previous post, it should probably go near the top of your "door" passage. That said, you haven't painted a complete picture of your setup, so I cannot be absolutely certain.
  • Ok, so I'll try to do it right now as best as I can.

    As for now, there's the starting passage that connects to the "Dungeon entrance" passage. Then there is a set of 20 passages and all of them are basically the same rooms just numbered 1-20. There's a macro placed in the exit link of "Dungeon entrance" passage that puts you randomly in one of those 20 rooms. Also, each room has a 50% chance to spawn North/South/East/West passage links (or any mix of them) each time player enters said room. All of them works the same as exit passage link from "Dungeon entrance", so they just launch the randomizer macro and put you in another random room. Room no. 1 is also the only room with the exit doors that lets you leave the dungeon.

    I hope that explains the structure of it, more or less.
  • edited October 2016
    A capsule description of the system is not really helpful in this case. I was referring more to the fact that you have not shown:
    1. The code for one of these passages, so we can see how you are, specifically, handling the exits.
    2. The code for your room exits macro—i.e. the one where you're choosing where an exit goes and setting the $lastPassage variable.
    Basically, when in doubt, show the code. A description of how the system is supposed to work is helpful, up to a point. Beyond that, however, concrete details become a necessity.


    And now, to touch upon something that I didn't comment on previously:
    Feren wrote: »
    […] also so I wouldn't have to place that markup in every random room passage.
    Widget macros. I'm not saying that you shouldn't write custom JavaScript macros, however, widgets are the solution to the quoted issue.
  • Ok, so time for some code pasting.

    First, what's inside each of the random rooms:
    11
    
    <<mAttack>>
    
    <center><<north>></center>
    <div id="textbox">\
    	<p class="alignleft"><<west>></p>\
    	<p class="alignright"><<east>></p>
    </div>
    <center><<south>></center>
    

    Now for passage link macro, which is really the same for each direction:\
    macros.north = {
    	"handler" : function(place, macroName, params, parser) {
    		var n = Math.floor((Math.random() * 2) + 1);
    		if (n == 1) {
    			new Wikifier(place, "<<link North>>>place <<dungeon>><</link>>");
    		}
    		if (n == 2) {
    			new Wikifier(place, "");
    		}
    	}
    }
    

    And finally, the code for my "randomizer". It probably looks terrible but that's the first solution I found on my own when I was trying to build randomly generated dungeon:
    macros.dungeon = {
    	"handler" : function(place, macroName, params, parser) {
    		var dungeon = params[0];
    		var random = Math.floor((Math.random() * 20) + 1);
    		if (random == 1) {
    			new Wikifier(place, "<<goto One>>");
    		}
    		if (random == 2) {
    			new Wikifier(place, "<<goto Two>>");
    		}
    		if (random == 3) {
    			new Wikifier(place, "<<goto Three>>");
    		}
    		if (random == 4) {
    			new Wikifier(place, "<<goto Four>>");
    		}
    		if (random == 5) {
    			new Wikifier(place, "<<goto Five>>");
    		}
    		if (random == 6) {
    			new Wikifier(place, "<<goto Six>>");
    		}
    		if (random == 7) {
    			new Wikifier(place, "<<goto Seven>>");
    		}
    		if (random == 8) {
    			new Wikifier(place, "<<goto Eight>>");
    		}
    		if (random == 9) {
    			new Wikifier(place, "<<goto Nine>>");
    		}
    		if (random == 10) {
    			new Wikifier(place, "<<goto Ten>>");
    		}
    		if (random == 11) {
    			new Wikifier(place, "<<goto Eleven>>");
    		}
    		if (random == 12) {
    			new Wikifier(place, "<<goto Twelve>>");
    		}
    		if (random == 13) {
    			new Wikifier(place, "<<goto Thirteen>>");
    		}
    		if (random == 14) {
    			new Wikifier(place, "<<goto Fourteen>>");
    		}
    		if (random == 15) {
    			new Wikifier(place, "<<goto Fifteen>>");
    		}
    		if (random == 16) {
    			new Wikifier(place, "<<goto Sixteen>>");
    		}
    		if (random == 17) {
    			new Wikifier(place, "<<goto Seventeen>>");
    		}
    		if (random == 18) {
    			new Wikifier(place, "<<goto Eighteen>>");
    		}
    		if (random == 19) {
    			new Wikifier(place, "<<goto Nineteen>>");
    		}
    		if (random == 20) {
    			new Wikifier(place, "<<goto Twenty>>");
    		}
    	}	
    }
    
  • First. Unless I've gone blind, you're not setting the $lastPassage (State.variables.lastPassage) variable anywhere in the macros you just showed. Where are you doing that?


    In The Meantime, Code Suggestions

    The <<north>> macro:
    • There's no need to quote handler here.
    • If you're not going to do anything for the 2 case, then simply don't do anything. Invoking the Wikifier with an empty string is silly.
    • You should terminate your assignment to macros.north with a semi-colon. Relying upon automatic semi-colon insertion will make you a sad panda when it bites you in the arse—and it probably will eventually.
    macros.north = {
    	handler : function (place, macroName, params, parser) {
    		var roll = random(1, 2);
    
    		if (roll === 1) {
    			new Wikifier(place, '<<link "North">>>place <<dungeon>><</link>>');
    		}
    	}
    };
    


    The <<dungeon>> macro:
    • Ditto not quoting handler and terminating the assignment with a semi-colon.
    • You do not use the dungeon variable anywhere. Loose it.
    • You've named your random number variable random, which shadows the random() function—because same name. If this is where you tried to use random() and it didn't work, as you claimed earlier, then that's why it didn't work. Give your variables unique names.
    • Your logic will select at most one case, however, you're testing all of them. Start using else if or, preferably, the switch statement.
    macros.dungeon = {
    	handler : function (place, macroName, params, parser) {
    		var
    			roll    = random(1, 20),
    			passage;
    
    		switch (roll) {
    		case 1:  passage = "One"; break;
    		case 2:  passage = "Two"; break;
    		case 3:  passage = "Three"; break;
    		case 4:  passage = "Four"; break;
    		case 5:  passage = "Five"; break;
    		case 6:  passage = "Six"; break;
    		case 7:  passage = "Seven"; break;
    		case 8:  passage = "Eight"; break;
    		case 9:  passage = "Nine"; break;
    		case 10: passage = "Ten"; break;
    		case 11: passage = "Eleven"; break;
    		case 12: passage = "Twelve"; break;
    		case 13: passage = "Thirteen"; break;
    		case 14: passage = "Fourteen"; break;
    		case 15: passage = "Fifteen"; break;
    		case 16: passage = "Sixteen"; break;
    		case 17: passage = "Seventeen"; break;
    		case 18: passage = "Eighteen"; break;
    		case 19: passage = "Nineteen"; break;
    		case 20: passage = "Twenty"; break;
    		}
    
    		new Wikifier(place, '<<goto "' + passage + '">>');
    	}	
    };
    
    That said, since you're simply mapping the numbers to their linguistic cardinals, you'd probably be better off simply using a generic object or an array to do so. For example: (using a generic object)
    macros.dungeon = {
    	handler : function (place, macroName, params, parser) {
    		var
    			roomMap = {
    				1  : "One",
    				2  : "Two",
    				3  : "Three",
    				4  : "Four",
    				5  : "Five",
    				6  : "Six",
    				7  : "Seven",
    				8  : "Eight",
    				9  : "Nine",
    				10 : "Ten",
    				11 : "Eleven",
    				12 : "Twelve",
    				13 : "Thirteen",
    				14 : "Fourteen",
    				15 : "Fifteen",
    				16 : "Sixteen",
    				17 : "Seventeen",
    				18 : "Eighteen",
    				19 : "Nineteen",
    				20 : "Twenty"
    			},
    			roll = random(1, 20);
    
    		new Wikifier(place, '<<goto "' + roomMap[roll] + '">>');
    	}	
    };
    
    Furthermore, I'm puzzled as to why you didn't simply use basic numerals for your room passage names—e.g. 1, 2, 3, etc.—which would have obviated the need for any kind of mapping. For example:
    macros.dungeon = {
    	handler : function (place, macroName, params, parser) {
    		var room = random(1, 20);
    
    		new Wikifier(place, '<<goto "' + room + '">>');
    	}	
    };
    
Sign In or Register to comment.