Jump to content

Moving carts


Venom

Recommended Posts

Hello. I am not quite certain if this is the correct board to be posting to, but I had a question in regards to scripting.

 

If one wanted to make multiple creatures move back and forth along long paths which would take many twists and turns, how would one go about that? The character must always travel in a straight line and never fidget or waver inbetween two waypoints. I'm trying to move mining carts along railroad tracks. This would need to be called continuosly while a party was in a town. So far I've been able to figure everything I've needed to do, but this one seems to be beyond me. I'll keep trying, but if someone has any ideas, I'd really appreciate them. I can't use waypoints as there are too many turns by too many carts. And the

Code:
  move_to_loc_x_y  
is quite odd. My carts just stop halfway there.
Link to comment
Share on other sites

Hmm, if I had to guess I would say that move_to_loc_x_y isn't working because the distance between the creature and the destination is to far for the pathfinding to work right. One way to do this I think, although it would be a big pain to code and may be to resource intensive, and would have to be hardcoded (meaning you need a specific script for each unique path although each one beyond the first should be much easier) would be to do the following

 

In the start state of the creature script, in a large amount of if then statments check its x,y location. At certain x,y locations, the creature script would change the number of one of the memory cells. You should have these locations not to far apart. Now the rest of the start state, would be dedicated to more if then statements, checking for the number in the memory cell. It would then take the number in the memory cell, and use that to tell the cart the way to the next x,y location that is recognized. (move_to_loc_x_y should work for small distances) Since you want them to go forward and back, instead of a loop as far as I can tell, have a second memory cell, that changes at either end and would represent the direction currently traveled.

 

Of course the real problem, is that such a script would take a large amount of time to write, as you have to manually write in each x,y location to check for, and where to go to next. Also if you have a second path a different cart needs to go by, you would have to create another copy of the script, and change the values so it goes on its own path.

 

Of course I've probably didn't get my idea across clearly enough and I would wait to see if anyone else had an idea that would be easier to implement.

 

One last thing, that I think might be a small problem no matter what approach you use is that unless you dictate the carts movement space by space, if a party member or other creature stood along the path, the cart would probably go off the track to pathfind around it. Can't think of a good way around this. Lining both sides of the track with blocked to creatures spaces would stop it from going off track, and would make giving the directions much easier, but it would make it almost impossible to use regular creatures in the same area.

Link to comment
Share on other sites

You have their scripts acting even while the party is at a distance, right?

 

Unless there is something blocking them from reaching their destination, the move_to_loc_x_y call should cause the affected monster to move there directly, regardless of current distance from the location.

 

Waypoints would definitely make things easier, but I think you can only have 8 per town.

 

Our ability to fine tune and work closely with the pathing engine is very limited because of the lack of pathing calls, and the engine cannot calculate complex paths (nor any extra requirements for said paths).

 

Because of this, making these moving cart creatures will be difficult. Finding a way to call a stop_moving function every time an obstruction is encountered would make things run in a stuttered, yet functioning fashion. But barring these tracks from the player would be the easiest course of action.

 

If these carts are unnecessary to the scenario, have them just visible to the player to add atmosphere, but make only a few of them. They would be generally inaccessible to the party.

Link to comment
Share on other sites

Thank you very much, both Linthar and Garrison. It's weird, because I started coding it exactly the way Linthar said about an hour after I posted. Weird, huh? Anyways, I have yet to test it, but I think it should work. I'm not entirely certain how I can get them to go back, but I have an idea. See, to differentiate each direction, I incremented a variable for each new path call. I think I can go backwards by subtracting one without having to re-enter all the x,y coordinates. It was very much a pain the first time I did it, and this will be the third such change I've done on that scale.

 

Just a sidenote: Garrison is correct in saying that the documentation provided says only eight. However, you can place ten in the game. I tried editing the source code for more, but the box can't fit more than one digit, and I have no idea how to change that.

 

Oh, and I was wondering; do you think that I need to manually code something to stop the cart if something obstructs it's path?

 

Thanks again for your help.

Link to comment
Share on other sites

Well, I tried my code, and it did not work. I've gone over it several times and I can't figure it out. I would like to post it here to see if anyone can find the error. Meanwhile, I'll keep searching.

Code:
 if	(dist_to_loc(get_memory_cell(4),get_memory_cell(5)) > 0) // checks to see if cart there		move_to_loc_x_y(ME,get_memory_cell(4),get_memory_cell(5)); // if not, goes there	else if		((0 < i < 15) && (ME == 10)) { // if there, calculate next route for cart #10			set_memory_cell(4,x);			set_memory_cell(5,y);			i = i + 1;			}	else if		((29 > i > 14) && (ME == 13)) {			stop_moving(ME);			set_memory_cell(4,x);			set_memory_cell(5,y);			i = i + 1;			}	else while		((36 > i > 28) && (ME == 14)) {			stop_moving(ME);			set_memory_cell(4,x);			set_memory_cell(5,y);			i = i + 1;			}	else while		((42 > i > 35) && (ME == 15)) {			stop_moving(ME);			set_memory_cell(4,x);			set_memory_cell(5,y);			i = i + 1;			}	else while		((54 > i > 41) && (ME == 16)) {			stop_moving(ME);			set_memory_cell(4,x);			set_memory_cell(5,y);			i = i + 1;			}	else while		((63 > i > 53) && (ME == 17)) {			stop_moving(ME);			set_memory_cell(4,x);			set_memory_cell(5,y);			i = i + 1;			}	else while		((68 > i > 62) && (ME == 18)) {			stop_moving(ME);			set_memory_cell(4,x);			set_memory_cell(5,y);			i = i + 1;			}	else while		((81 > i > 67) && (ME == 19)) {			stop_moving(ME);			set_memory_cell(4,x);			set_memory_cell(5,y);			i = i + 1;			}			if // sample paths	(i == 1) {		x = 55;		y = 53;		}if	(i == 2) {		x = 52;		y = 53;		}if	(i == 3) {		x = 52;		y = 49;		}if	(i == 4) {		x = 57;		y = 49;		}if	(i == 5) {		x = 57;		y = 40;		} // 400 lines more of this
I set i = 1 in INIT_STATE, and I set mem_cells 4 and 5 to the carts starting location in INIT_STATE. I also declared the variables, if you were wondering.
Link to comment
Share on other sites

Now, not to sound lazy or discouraging, but seriously, work around it. Is this a hostile town? If so why would people still be pushing carts around (Unless they're magical). How many carts do you plan on having? Do you realize how much memory it will take up just have the minor cool effect? Death at Chapmans had some cool sound effects in the school, and it screwed the entire level over because of the memory it ate.

Link to comment
Share on other sites

Hmm, I just noticed I posted the wrong code. Only the first nine lines of the initial if statement are valid. I hadn't changed the rest to match yet. The i,x,y statements are ok, though.

 

I don't think it will take up too much memory, as I am having the carts only act at a distance. That may be a bit unrealistic however. And this is a friendly town. And the carts are magical. And there are eight carts. I may have to keep them stationary, but until everything else has been exhausted, I'm not ready to give up.

Link to comment
Share on other sites

ME always equals -1. You have to use my_number() for the conditionals that try to determine which cart the script is running for.

 

Multiple comparisons cannot be placed together (a < b < c). This is not a user friendly scripting engine! If this is possible in C, then that is news to me.

 

After skimming through the heart of the script, I think that it has some unneeded complexity in it. This causes making it work correctly more difficult. This may already be the best way of doing it, but I would have to think more about this in order to give you a definitive answer.

Link to comment
Share on other sites

I've revised my code and, as I have done before, I anticipated some of the problems that Garrison points out. Very odd coincidences. Here is a revised sample of the code:

Code:
 if	(dist_to_loc(get_memory_cell(4),get_memory_cell(5)) > 0)		move_to_loc_x_y(ME,get_memory_cell(4),get_memory_cell(5));	else if		((i <= 14) && (my_number() == 10)) {			i = i + 1;			set_memory_cell(4,x);			set_memory_cell(5,y);			}	else if		((i >= 15) && (i <= 28) && (my_number() == 13)) {			i = i + 1;			set_memory_cell(4,x);			set_memory_cell(5,y);			}if	(i == 1) {		x = 55;		y = 53;		}if	(i == 2) {		x = 52;		y = 53;		}if	(i == 3) {		x = 52;		y = 49;		} 
I figured out the ME thingy, but instead of the far simpler way of my_number, I had assigned a preset memory cell to the creature number. The multiple comparisons I had also changed previously, but I had no idea why. It gave me no error when testing, which, sadly, none of this does. However, I was running out of ideas and though that did not solve the problem entirely, at least it was constructive. The carts, as of this post, still sit there. Argh. I'm going to bed.
Link to comment
Share on other sites

I love you, Thuryl! I would have never thought of that, and it turned out several portions were not being called. This gave way to a massive overhual of my script and scenario. I simplified the scenario so that the carts did not intersect, ever. This required deletion of three carts, which drastically reduced the amount of script. Then I rewrote the script into a new format, consisting of one big if statement.

 

After several hours testing this, however, I'm lost again (really, this doesn't happen often). Thanks to Thuryl, I know that my last else statement is not getting called. It just keeps calling the first if "bit". I can get it to call the else, but it only calls it once and then returns to repeating the if "bit". And this without moving. I'm just not sure why it won't move. Here is the code, if I could ask for your,(forum members), help once more. I'm going to post almost all of it this time, to get a better view.

Code:
 // something2.txt// Neither simple, nor naive, this text has the creature follow a certain route.// Memory Cells://   Cell 1,2 - Stuff done flag. If both 0, nothing. Otherwise when this //     is killed, set to 1. (Example: If cell 1 is 3 and cell 2 is 5, when//     creature is killed, sets SDF(3,5) to 1.)//   Cell 3 - Dialogue node to start with if talked to. if left at 0, this//     character doesn't talk.//   Cell 4 - X coordinate to move to.//   Cell 5 - Y coordinate to move to.begincreaturescript;variables;short i = 1;short target;short x = 0;short y = 0;body;beginstate INIT_STATE;	break;beginstate DEAD_STATE;	// Set the appropriate stuff done flag for this character being dead	if ((get_memory_cell(1) != 0) || (get_memory_cell(2) != 0))		set_flag(get_memory_cell(1),get_memory_cell(2),1);break;beginstate START_STATE;// Start ifs for cart #13if	(i == 1) {		x = 52;		y = 53;		}if	(i == 2) {		x = 52;		y = 49;		}if	(i == 3) {		x = 57;		y = 49;		}if	(i == 4) {		x = 57;		y = 40;		}if	((dist_to_loc(get_memory_cell(4),get_memory_cell(5)) > 0) && (i <= 13) && (i != 0) && (my_number() == 13)) {		print_str("Testing 1.0");		move_to_loc_x_y(my_number(),get_memory_cell(4),get_memory_cell(5));	}	else if	((dist_to_loc(get_memory_cell(4),get_memory_cell(5)) > 0) && (i >= 14) && (i <= 18) && (my_number() == 15)) {		print_str("Testing 1.1");		move_to_loc_x_y(my_number(),get_memory_cell(4),get_memory_cell(5));	}	else if	((dist_to_loc(get_memory_cell(4),get_memory_cell(5)) > 0) && (i <= 26) && (i >= 19) && (my_number() == 17)) {		print_str("Testing 1.2");		move_to_loc_x_y(my_number(),get_memory_cell(4),get_memory_cell(5));	}	else if	((dist_to_loc(get_memory_cell(4),get_memory_cell(5)) > 0) && (i <= 30) && (i >= 27) && (my_number() == 18)) {		print_str("Testing 1.3");		move_to_loc_x_y(my_number(),get_memory_cell(4),get_memory_cell(5));	}	else if	((dist_to_loc(get_memory_cell(4),get_memory_cell(5)) > 0) && (i <= 40) && (i >= 31) && (my_number() == 19)) {		print_str("Testing 1.4");		move_to_loc_x_y(my_number(),get_memory_cell(4),get_memory_cell(5));	}	else {		print_str("Testing A");		i = i + 1;		set_memory_cell(4,x);		set_memory_cell(5,y);	}break;beginstate TALKING_STATE;	if (get_memory_cell(3) == 0) {		print_str("It's a cart.  It doesn't talk.");		end();		}break; 
Link to comment
Share on other sites

Well, in theory, no. The initial if statement should only allow the else statement to be called if the cart is at an x,y coordinate. The carts can't move until they have coordinates in mem_cell 4 and 5. When the script is first run, there is nothing there and i = 0. I'm not sure if that makes the get_memory_cell() call false, but to ensure it, I place the i != 0. Since it is false, it goes to the else statement. This is the tricky part.

The first else statement does not set anything for the mem_cells. It only increments i. Wait, hold on. The light just went on! I know what I did wrong! Yippee! I think that the program beleives that nothing in mem_cells 4 and 5 is a number. It can't go to nothing, but the statement is true. This doesn't cause it to keep incrementing. Rather, it just keeps trying to go to 0,0 (the status of the mem_cells). Well, inadvertenly, Garrison, you have helped me greatly. My thanks to you. I think what I should do is kill the (i != 0) in the first part, and manually enter in the first coordinates for each cart. I'll let you know if this works. Thanks again.

Link to comment
Share on other sites

Ha ha ha ha ha ha ha! Mua ha ha ha ha ha ha! She lives!

 

Whew, glad to get that out of my system. The 32 hour mark has just passed and I have it working. It does not slow down gameplay, or demand heavily of the processor (I should know, I run a 533mHz Celeron). The last, small bug, is that whenever the party moves in the way of the cart, everything is messed up and the cart goes wacko. I have given each cart it's own creature script, which, though annoying, seemed necessary. They are all identical except for the coordinates.

 

Here is a portion of the shortest one:

Code:
 // Start checking for cart position and then give cart directions for next destinationif	(i == 1) {		x = 9;		y = 43;		}if	(i == 2) {		x = 9;		y = 34;		}if	(i == 3) {		x = 11;		y = 34;		}if	(i == 4) {		x = 9;		y = 34;		}if	(i == 5) {		x = 9;		y = 43;		}if	(i == 6) {		x = 6;		y = 43;		}if	(i == 7) {		x = 6;		y = 54;		}if	(i == 8) {		i = 0;		x = 6;		y = 43;	}if // If cart is stopped, recalculate movement vector	((am_i_doing_action() == 0) && (i <= 8)) {		print_str("Testing 17");		move_to_loc_x_y(ME,get_memory_cell(4),get_memory_cell(5));		i = i + 1;		set_memory_cell(4,x);		set_memory_cell(5,y);	} 
If you guys could just help me out on this last bit, it would really help me out. I'm doing this for a school project and it's due in a few months. It's supposed to be on an epic scale.
Link to comment
Share on other sites

Quote:
Originally written by Venom:
They are all identical except for the coordinates.
Might I suggest memory cells usage? I haven't really followed what you're doing, but if you have ten or fewer coordinates that you're feeding each script, you only have to write one.

EDIT: And a quick skim shows me that you're already using some memory cells, although not, as far as I can tell, very many. Eh.
Link to comment
Share on other sites

Yes, I am doing this for school. It's actually my senior project.

 

And yes, I was using memory cells 4 and 5 for coordinates x and y, respectively. What exactly did you mean, Kelandon, about the memory cells? In my current format, I must double all my coordinates to loop the travel. I do have less than ten coordinates for each cart, though, not doubled.

Link to comment
Share on other sites

You may be able to use roads to achieve the affect you want. For example set the cart tracks as a road and then tweak the creature script so it will only move on roads. Another idea is script the track terrains to work something like conveyor belts and depending on a variable it would move any cart object on the track forward or backward. Once the cart reaches the end of the track the variable would be switched and it would move in the oposite direction.

Link to comment
Share on other sites

Kelandon: There are multiple scripts. I had wanted one script, but after many hours of tweaking, it seemed unfeasible. If you know something that you really think would work, I'd love to hear it.

 

Kennedy: I already looked into the roads option. Unfortunately, that only works for objects set on the terrain. This is terrain. The conveyor belt idea I had never thought of before. Does BoA use conveyors? I am pretty sure none of the scenarios created had any. It's been a few years, but I don't even remember if Avernum I or II had them. I never played Avernum III, and I don't know how they would fix the golem place without conveyors. Only remember Exile III style conveyors (greatest game made by SpidWeb, bar none!). If you could explain a little more, though, I'd be very interested. Can they be pushed off, though? And what happens if they are blocked? Thanks.

Link to comment
Share on other sites

Eh, I suppose I will have to read exactly what you're doing and how you're doing it. But if you have few enough coordinates that you're feeding the scripts, and if those coordinates are the only differences between the scripts, you can use memory cells 0-3 and 6-9 for those differences and only use one script. Just set memory cells.

 

I am a big proponent of memory cell usage, as it makes scripts reusable both by the designer and by others. I will actually read what you're doing and take a closer look at it to provide a more specific suggestion later.

Link to comment
Share on other sites

Dastal: I don't beleive that is possible, for each would need to be called one after another. I tried something similar with the move_to_loc_x_y, but it would need to be called every turn, it did not overlap (meaning each cart would move only after the last one moved), and, worst of all, you couldn't move, the processor usage was so high.

 

Kelandon: I think I see what you mean, and I may post a copy for others to use. You would set the appropriate coordinates in the mem_cells you wished to use. Then, you could write a script, which would check each one, see what they were, and then go there. You would also need to make sure the mem_cell wasn't set to 0; if so, the script should be written to skip it. The only hard part would be knowing when to get the next coordinate. I think you could use the incrementing i format, where the first call would be made when i == 1, and then increment, calling only when the cart stopped.

 

I guess another hard bit would be getting the cart to go back, but I think it's doable. The only limitation I can see is that at max, it can only store five x,y coordinates. This makes it unusable for my scenario.

 

Thuryl: How did SpidWeb do the conveyor belts in the golem tower in Avernum III? I'm assuming that if there are no premade conveyors in BoA, then none in Avernum III. I think that conveyors would be only be cool if the thing being conveyed could not be pushed off. Realistically, why would anyone randomly shove a mining cart over in the middle of a mine?

Link to comment
Share on other sites

Ah well. Maybe you could only exectute the creature script when the party is nearby, so only one cart would be moving at once?

 

Also, if the party trys to get in the way of the moving car, you could just move them off the script and give them a little damage on the basis of "being hit by a fast moving mine cart HURTS!"

Link to comment
Share on other sites

I could never get through the Golem's in E3. Heck, it took me forever to get through the E3 New Factory (is it just me, or was ther no real "new factory" in A3?). I never did beat it, since I cast quickfire into Rentar's courtyard, and then I couldn't contain it, and my last save was like before I finsihed the Trogo/Giants. Part of that, I think, was just unfamiliarity with the way it all worked (I mean, I was like 12 at the time, the first time I played it, at 10, I couldn't even beat the slimes). When I came back to playing A1, A2, and A3, I beat all of them, doing everything I could, in a bit over a day each of non-stop playing. [Hey! That's just how I am. I pulled the same trick with WC1+2, and then WC3 when I got it, NWN, EE, AoK, DS, C&C (all of 'em), and a bunch of others.]

Link to comment
Share on other sites

Pachal: It really does not matter when they are moving. The change in game speed is unnoticeable (at least to me), and it would just be more work to change them now. I also noticed that the method you are describing could very easily be done with the set_script_mode() call. The # you input in the brackets affects when the script is called.

 

Dastal: I like your suggestion, but we're going to have to assume that the carts are controlled by beings who care about others. The tracks need to be crossed often by miners and if we have speeding mining carts rushing heedlessly along, disaster would be all too common. And also, the tracks need to be crossed to get around the mine.

 

And yeah, the laser thing sounds kind of lame. The conveyor belt puzzle was stinking hard, I think the hardest puzzle in Exile III. It took me hours of pulling out my hair and cursing at the endless golems plopping out of nowhere to figure it out. I can't imagine a laser puzzle really fitting the theme, either.

Link to comment
Share on other sites

Venom, I have perhaps an easier idea. Why not make the carts move through their own tunnels? That's the way it is in a lot of mines. Then you could have a few carts each at the cross-tracks. You could even use a light system (using laser power globes) to notify the party when there is a train comming. That way if they try and cross the track, it's their own damn fault! The script is way simplified. The car just needs to move like 16 spaces in a straight line. If you want another track crossing, you just have one car getting to a certain point activate another car to move. An even easier way would be to have every car move simultaneously, every 32 moves or so. The player would only see one car at a time, so you would have a great illusion. Or maybe have the cars run in trenches of some kind? Though making a bridge could be a bit of a pain. Not sure how you'd do that. Just some thoughts.

Link to comment
Share on other sites

Thanks, Dastal, thats the best idea I've heard yet! I think it would be easy to code, or at least simple. I could even make a new town, accessible from the mine, which would be crisscrossed with these tunnels. The lights thing is a nice touch. Yeah, I might use that when I finish some more critical areas.

 

However, if anyone knows of a technical workaround, without having to rearrange the layout, of seeing if a party member was in the path, pausing, and then moving again, I'd be grateful. I just had an epiphany of what I could do. I must go try it.

Link to comment
Share on other sites

I know, I know. I replaced Omlette, who was moderator of both boards, so I sort of got both boards by default. However, moderating any of the normal game boards really is a matter of knowing what online resources are available (all of my answers for A1 come from and include links to Avernum Annotated Maps, for example) rather than knowing the games really well.

Link to comment
Share on other sites

Guest
This topic is now closed to further replies.
×
×
  • Create New...