Page 2 of 3
Re: variable
Posted: Sat Mar 13, 2004 4:16 pm
by Bjarne BZR
dcoshea wrote:
Code: Select all
local.a = $my_entity
local.a.b = 1
This is just my experience with normal programming languages. It's the reason I was questioning what level.axis_prison was set to before level.axis_prison.busy was set.
I'd use the method quoded above.
Havent really done
level.x.y.d.e.r = x style references, and I don't know if it works. But as it is a scripting language it MAY work ( I hope not

).
Only one way to find out if you really want to know: try.
Re: variable
Posted: Mon Mar 15, 2004 5:39 am
by dcoshea
Bjarne BZR wrote:Havent really done
level.x.y.d.e.r = x style references, and I don't know if it works. But as it is a scripting language it MAY work ( I hope not

).
Only one way to find out if you really want to know: try.
I'll just assume it acts like a normal scripting language until proven otherwise
Regards,
David
Posted: Tue Mar 16, 2004 1:17 am
by nuggets
only a depth of one can be used for an entity and then the variable
so $player.a_test would be fine
$player.a.b_test would result in an error
$player.a = $chair
$player.a.b would be fine
$player.origin
$table.player = ***
$chair.table = ***
$player.chair = ***
$player.chair.table.player.origin would be fine
Posted: Tue Mar 16, 2004 1:54 pm
by bdbodger
I usually do it like this $player[a][a] $player[a] etc
Posted: Tue Mar 16, 2004 2:03 pm
by dcoshea
bdbodger wrote:I usually do it like this $player[a][a] $player[a][ b] etc
[Edit: put space before b so it's not picked up as a tag]
I don't understand what that means - $player, presumably, refers to only one player (i.e. single-player mode), so in this case $player is an object of type Player and a two-dimensional array
at the same time? In multi-player, would $player[local.i][somearrayindex] work?
That's pretty weird stuff!
Regards,
David
yes
Posted: Tue Mar 16, 2004 2:50 pm
by tltrude
It can be used in multiplayer. Maybe you guys can help me to understand how these threads work--they do work very well too. I'm using them, as you can see, to automatically raise the health of a trigger_multiple according to the number of allied players that enter a game. I created the second thread, but the first one was created by jv_map.
I know it works, but don't really know how it works, and would like to. Thread "missle_autohealth" is called from level waittill spawn, and "missile_feedback" is where the health is change to a precentage for printing on the screen. My bacis questions are, how does a "for" loop work, and what makes it stop looping?
Code: Select all
//*** --------------------------------------------
//*** Automatic difficulty threads
//*** --------------------------------------------
getnumberallied:
local.j = 0
for(local.i = 1; local.i <= $player.size; local.i++)
{
local.player = $player[local.i]
if(local.player.dmteam == allies)
local.j++
}
end local.j
missle_autohealth:
wait 10
local.numallies = waitthread getnumberallied
if (local.numallies > 1)
{
level.missle_health = ((level.missle_health * local.numallies) - (local.numallies * 1000))
}
$missle_ex_trigger.health = level.missle_health
iprintln "Automatic difficulty set for " (local.numallies) " Allied players."
iprintln "Missile Health: " (int($missle_ex_trigger.health))
thread missle_feedback
end
By the way, "level.missle_health" starts at 8000 in prespawn. And, there are 16 allied spawn spots.
Re: yes
Posted: Tue Mar 16, 2004 3:04 pm
by dcoshea
tltrude wrote:It can be used in multiplayer. Maybe you guys can help me to understand how these threads work
In the code below, there's only one array index, not two (i.e. the $player array is not being treated as two dimensional, aka a list of lists or array of arrays), so it's not convincing me about this weird making-things-into-arrays stuff

Anyway maybe you weren't trying to do that
I documented the code a bit, my comments are in bold [Edit: well, at least they're surrounded by bold tags which the forum is ignoring]:
Code: Select all
//*** --------------------------------------------
//*** Automattic difficulty threads
//*** --------------------------------------------
getnumberallied:
local.j = 0 [b]// initialize count of Allied players to 0[/b]
for(local.i = 1; local.i <= $player.size; local.i++) [b]// loop through player indices[/b]
{
local.player = $player[local.i] [b]// get a Player object[/b]
if(local.player.dmteam == allies)
local.j++ [b]// this player is on the Allied team, so add 1 to the count of Allied players[/b]
}
end local.j [b]// return the count to the calling thread[/b]
missle_autohealth:
wait 10
local.numallies = waitthread getnumberallied [b]// gets the number of Allied players[/b]
if (local.numallies > 1) [b]// if there is more than one Allied player..[/b]
{
level.missle_health = ((level.missle_health * local.numallies) - (local.numallies * 1000)) [b]//.. then set level.missile_health to ???[/b]
}
$missle_ex_trigger.health = level.missle_health [b]// set the health of the trigger to the value calculated above[/b]
iprintln "Automattic difficulty set for " (local.numallies) " Allied players." [b]// display a mis-spelled message :)[/b]
iprintln "Missile Health: " (int($missle_ex_trigger.health))
thread missle_feedback
end
I hope this helps! I find the calculation of the new missile_health value strange - it calculates the new value based on the old value. If we knew what the initial value of level.missile_health was before this code modified it, it would help!
The calculation:
Code: Select all
level.missle_health = ((level.missle_health * local.numallies) - (local.numallies * 1000))
can be simplified to:
Code: Select all
level.missle_health = local.numallies * (level.missle_health - 1000)
if my math is correct! So basically I guess if level.missile_health starts off as 2000, then you're setting the health to 1000 times the number of Allied players. Unless level.missile_health is calculated somehow before this point (i.e. it's not set to a constant before this code), you may as well just do:
Code: Select all
level.missile_health = local.numallies * 1000
or something like that.
Hope this helps, and the last bit about the calculation isn't irrelevant
Regards,
David
spelling
Posted: Tue Mar 16, 2004 3:22 pm
by tltrude
The only thing useful in your comments is the mis-spelled word. My bacis questions are, how does a "for" loop work, and what makes it stop looping?
As I said, I wrote the second thread, so did not need and explanation of it.
Posted: Tue Mar 16, 2004 10:39 pm
by Bjarne BZR
A for loop:
Code: Select all
for ( INIT_STATEMENT ; TEST_STATEMENT ; INCREMENT_STATEMENT ) {
BLOCK_OF_CODE
}
The
INIT_STATEMENT will be executed only once when the for is reached. It is typically used to initialize a vatiable that will be used as a counter.
Typically:
The
TEST_STATEMENT will be executed
before each loop of execution of the code in
BLOCK_OF_CODE. Depending on what this execution returns, whe for loop will be continued or not. If the result is true ( that is: not a 0 value ) the looping goes on for another round.
Typically:
The
INCREMENT_STATEMENT will be executed
after each loop of execution of the code in
BLOCK_OF_CODE.
Typically:
Example 1:
Code: Select all
for ( local.index=0 ; local.index < 3 ; local.index++ ) {
println "Index: " local.index
}
...will print (in console):
not
Index: 3, because
INCREMENT_STATEMENT will be executed
after each loop: meaning local.index becomes 3 and the
TEST_STATEMENT fails, and the for is aborted.
Example 2:
Code: Select all
for ( ; 1 ; ) {
println "I won't use GOTO statements again, because I have seen the FOR light."
wait 1
}
...will write the text once a second for ever ( or until the map is exited)
Posted: Wed Mar 17, 2004 3:47 am
by nuggets
basically it's a goto loop until all events have been met
for (local.i = 1;local.i<=3;local.i++)
creates a counter that starts at 1
does each command in the loop while it's less than or equal to 3
tells the counter to change and start again
so
for (local.i=1; local.<=3; local.i++)
{
iprintln_noloc "TOMS INTRO TO FOR LOOPS PART " local.i
}
will give you...
local. i = 1
will_do:
if (local.i <= 3)
{
do action
local.i++
goto will_do
}
else
{
end
}
Posted: Wed Mar 17, 2004 10:04 am
by dcoshea
For anyone who thinks that indenting makes code easier to read
nuggets wrote:Code: Select all
local. i = 1
will_do:
if (local.i <= 3)
{
do action
local.i++
goto will_do
}
else
{
end
}
Posted: Wed Mar 17, 2004 12:28 pm
by bdbodger
For the thread by JV it is used like this
Code: Select all
local.num = waitthread getnumberallied
getnumberallied:
local.j = 0
for(local.i = 1; local.i <= $player.size; local.i++)
{
local.player = $player[local.i]
if(local.player.dmteam == allies)
local.j++
}
end local.j
the thread returns the value local.j after the word end back to the line that called it so local.num = the returned value from the thread which is the value of local.j after the thread is done .
For the array thing if I wanted to store values in the $player array I can do it the first element is of course is $player[1] for example but I can add values to that array . Usually I dont do it for a player but it can be done . like I can do
$player[1]["somestring"][1] = 10
$player[1]["somestring"][2] = 20
normally I do it for a level variable like in my strafe script where I number the nodes level.strafenode[set #][node #].origin etc but I am fairly sure that the $player array is like any other array except that the indexing starts at 1 not 0 .
thanks
Posted: Sat Mar 20, 2004 6:00 am
by tltrude
Thanks, guys! That helps a lot.
Posted: Sat Mar 20, 2004 8:14 am
by dcoshea
bdbodger wrote:For the array thing if I wanted to store values in the $player array I can do it the first element is of course is $player[1] for example but I can add values to that array . Usually I dont do it for a player but it can be done . like I can do
$player[1]["somestring"][1] = 10
$player[1]["somestring"][2] = 20
normally I do it for a level variable like in my strafe script where I number the nodes level.strafenode[set #][node #].origin etc but I am fairly sure that the $player array is like any other array except that the indexing starts at 1 not 0 .
Well I don't see it being that surprising that you could make a variable level.strafenode which is actually a two-dimensional array. I mean, you could easily declare something like that in C:
Code: Select all
typedef struct {
[...]
vector_t origin;
[...]
} node_t;
typedef struct {
[...]
node_t strafenode[MAX_SET_NUM][MAX_NODE_NUM]; // a 2D array of pointers to nodes
[...]
} level_t;
level_t level;
'level.strafenode[x][y].origin' would be a valid thing to reference in that C code.
However, with your $player example, it wouldn't be a simple matter like that because, for any valid player index n, $player[n] is both an object of type Player with a number of fields
and it is a two dimensional array. The only way something like that would make sense in C is if $player[n] was of a 'union' type, but that wouldn't be what you're using here, you're using two separate sets of storage. It's more like this:
Code: Select all
tyepdef struct {
vector_t origin;
int health;
[...]
} player_t;
typedef struct {
player_t the_player;
int the_other_data[MAX_MAJOR_INDEX][MAX_MINOR_INDEX];
} player_wrapper_t;
player_wrapper_t player[MAX_PLAYERS];
In that case, you could use 'player[1].the_player.origin' to get the player's origin and 'player[1].the_other_data[1][2] = 10' to access that array (of course C doesn't allow you to use strings as array indices), but note that you need to distinguish between whether you are accessing 'the_player' or 'the_other_data'.
I can see how your level.strafenode example works, it makes perfect sense, but I don't know how you could make '$player[n]' refer to both the Player object and some other array you made up at the same time. If you replaced '$player[1]["somestring"][1] = 10' with '$player[1].
mydata["somestring"][1] = 10' it'd make a lot more sense to me.
Of course I don't know everything about the language but it just seems weird
Regards,
David
Posted: Sat Mar 20, 2004 5:53 pm
by bdbodger
Well here is something I did in a script but later stoped doing for other reasons but it did work
Code: Select all
thread ai_add_task level.friendly3 1 "wait" 4
Code: Select all
ai_add_task local.ai local.sequence local.action local.parm1 local.parm2 local.parm3 local.parm4 local.parm5:
if !(isalive local.ai)
end
while (local.ai.isupdating == 1)
wait .5
local.ai.isupdating = 1
local.ai.index++
local.ai.sequence[local.ai.index] = local.sequence
local.ai.action[local.ai.index] = local.action
local.ai.parm1[local.ai.index] = local.parm1
local.ai.parm2[local.ai.index] = local.parm2
local.ai.parm3[local.ai.index] = local.parm3
local.ai.parm4[local.ai.index] = local.parm4
local.ai.parm5[local.ai.index] = local.parm5
local.sequence = NIL
local.action = NIL
local.parm1 = NIL
local.parm1 = NIL
local.parm2 = NIL
local.parm3 = NIL
local.parm4 = NIL
local.parm5 = NIL
local.ai.isupdating = 0
end
Code: Select all
ai_do_tasks:
ai_do_tasks_reset:
self waittill trigger
if( level.debug == 1)
iprintln "running tasks"
ai_do_tasks_loop:
while(self.isupdateing ==1)
wait 1
if !(isalive self)
end
while (self.sequence[1] > $player.sequence)
waitframe
if(self.action[1] != NIL)
{
if(level.debug == 1)
{
iprintln "self sequence is " self.sequence[1]
iprintln "player sequence is " $player.sequence
}
switch( self.action[1])
{
wait:
wait self.parm1[1]
break
.....
.....
}
if!(isalive self)
end
self.isupdateing = 1
// bump the tasks list
for (local.i = 1 ; local.i < self.index ; local.i ++)
{
self.sequence[local.i] = self.sequence[local.i+1]
self.action[local.i] = self.action[local.i + 1]
self.parm1[local.i] = self.parm1[local.i + 1]
self.parm2[local.i] = self.parm2[local.i + 1]
self.parm3[local.i] = self.parm3[local.i + 1]
self.parm4[local.i] = self.parm4[local.i + 1]
self.parm5[local.i] = self.parm5[local.i + 1]
}
// clear last index
self.sequence[self.index] = NIL
self.action[self.index] = NIL
self.parm1[self.index] = NIL
self.parm2[self.index] = NIL
self.parm3[self.index] = NIL
self.parm4[self.index] = NIL
self.parm5[self.index] = NIL
self.index--
if(self.index != 0 )
{
self.isupdateing = 0
waitframe
if(isalive self)
goto ai_do_tasks_loop
}
self.isupdating = 0
if(isalive self)
goto ai_do_tasks_reset
end