Cool Pog Tricks
20 years 8 months ago #9230
by MajorTom
Replied by MajorTom on topic Cool Pog Tricks
Actually it wasn't stations but gunstars that had a station avatar. They were type icShip.
I played around with the following task for the MP game. The purpose was to set a "station" gunstar from neutral to hostile to the players faction whenever a player had fired at it. The task then resets the gunstar to neutral whenever the player is more than 15 km away from it, but everytime he gets within 15 km it goes hostile again. (This never came into actual usage in the MP game because I would need to create a faction dynamically for each player that entered the game). It does however show you a little about how the iShip.Attacked function works:
The debug readout is like this:
SCRIPT: [unknown] WRMOD: sim was attacked: 16779278 ("CMC_Supply", "icShip")
SCRIPT: [unknown] attacked status is: 0
SCRIPT: [unknown] WRMOD: reset to ! shot:
SCRIPT: [unknown] attacked status is now: 0
FLUX: [unknown] Bcast Message "^shot station now hostile"
FLUX: [unknown] Bcast Message "^now neutral at 18 km"
FLUX: [unknown] Bcast Message "^moving in to 15 km"
FLUX: [unknown] Bcast Message "^now hostile at 15.2 km"
FLUX: [unknown] Bcast Message "^moving out"
FLUX: [unknown] Bcast Message "^now neutral at 16 km"
Notes: Bcast Message is an ingame chat message I sent to myself during gameplay to document what I was doing.
(!) Although the script will alternate between hostile and neutral every time you get closer than 15 km, the script only runs through the debug part once because (iSim.Attacked( got_shot ) == true)
is only true once (in this case).
Sorry, but after looking at the code more closely (I did it about a year ago) I notice, that it works by simply alternating the faction and only changes the attacked status once (it doesn't alternate hostility by alternating the attacked status).
Iwar2 Multiplayer Fan Site
I played around with the following task for the MP game. The purpose was to set a "station" gunstar from neutral to hostile to the players faction whenever a player had fired at it. The task then resets the gunstar to neutral whenever the player is more than 15 km away from it, but everytime he gets within 15 km it goes hostile again. (This never came into actual usage in the MP game because I would need to create a faction dynamically for each player that entered the game). It does however show you a little about how the iShip.Attacked function works:
Code:
task CheckForAttackers ( hsim touch)
{
hship got_shot, attacker;
string message;
list gunstar_list = List.FromSet ( iSim.SimsInRadius ( iSim.Cast ( touch ), 160000, T_Gunstar ));
hfaction faction;
int n, gunstars = List.ItemCount ( gunstar_list );
schedule
{
every 2:
{
// walk through the map and check if a Gunstar Station has been attacked
for ( n = 0; n< gunstars; ++n )
{
got_shot = iShip.Cast( List.GetNth( gunstar_list, n ) );
attacker = iShip.Cast( iSim.LastAttacker( got_shot ));
if ( iSim.Faction( attacker ) == iFaction.Find( Text.Field("mp_flag_team_b", FT_Text) ) )
{
faction = iFaction.Find( Text.Field("mp_flag_team_a", FT_Text));
message = Text.Field("mp_flag_team_a", FT_Text);
}
else
{
faction = iFaction.Find( Text.Field("mp_flag_team_b", FT_Text));
message = Text.Field("mp_flag_team_b", FT_Text);
}
iSim.SetFaction( iSim.Cast(got_shot), faction );
iMultiplay.ServerSendUserMessage( 308, none, got_shot, message );
if (Sim.DistanceBetween (got_shot, attacker) > 15000)
{
iSim.SetFaction( iSim.Cast(got_shot), iFaction.Find("Neutral") );
if (iSim.Attacked( got_shot ) == true)
{
Debug.PrintString( "WRMOD: sim was attacked: " );
Debug.PrintHandle( got_shot );
Debug.PrintString( " \n" );
Debug.PrintString( "attacked status is: " );
Debug.PrintInt( iSim.Attacked( got_shot ) );
Debug.PrintString( " \n" );
! iSim.Attacked( got_shot );
Debug.PrintString( "WRMOD: reset to ! shot: " );
Debug.PrintString( " \n" );
Debug.PrintString( "attacked status is now: " );
Debug.PrintInt( iSim.Attacked( got_shot ) );
Debug.PrintString( " \n" );
}
iMultiplay.ServerSendUserMessage( 306, none, got_shot, "" );
}
} //for
}
} //schedule
}
The debug readout is like this:
SCRIPT: [unknown] WRMOD: sim was attacked: 16779278 ("CMC_Supply", "icShip")
SCRIPT: [unknown] attacked status is: 0
SCRIPT: [unknown] WRMOD: reset to ! shot:
SCRIPT: [unknown] attacked status is now: 0
FLUX: [unknown] Bcast Message "^shot station now hostile"
FLUX: [unknown] Bcast Message "^now neutral at 18 km"
FLUX: [unknown] Bcast Message "^moving in to 15 km"
FLUX: [unknown] Bcast Message "^now hostile at 15.2 km"
FLUX: [unknown] Bcast Message "^moving out"
FLUX: [unknown] Bcast Message "^now neutral at 16 km"
Notes: Bcast Message is an ingame chat message I sent to myself during gameplay to document what I was doing.
(!) Although the script will alternate between hostile and neutral every time you get closer than 15 km, the script only runs through the debug part once because (iSim.Attacked( got_shot ) == true)
is only true once (in this case).
Sorry, but after looking at the code more closely (I did it about a year ago) I notice, that it works by simply alternating the faction and only changes the attacked status once (it doesn't alternate hostility by alternating the attacked status).
Iwar2 Multiplayer Fan Site
Please Log in or Create an account to join the conversation.
20 years 8 months ago #9239
by Qi Qi
Life is half spent before we know what it is...
Replied by Qi Qi on topic Cool Pog Tricks
Hi Tom, I appreciate your helps very much. Now I have finished the latest improvements over Skull Squadron. You can check out it later.
Life is half spent before we know what it is...
Life is half spent before we know what it is...
Life is half spent before we know what it is...
Please Log in or Create an account to join the conversation.
- GrandpaTrout
- Topic Author
- Offline
- King of Space
20 years 6 months ago #9724
by GrandpaTrout
Replied by GrandpaTrout on topic Cool Pog Tricks
Pog Linker Issue:
The POG linker cannot handle circular dependency between pog packages. This can happen very easily. Say you have a station.pkg
that gets called when the player arrives near a station. The station.pkg calls guard.pkg to create some guards for the station. The guard.pkg calls back to the station.pkg to find out what kind of station it is (so it can pick the proper kind of guards).
station.pkg calls guard.pkg. Guard.pkg call station.pkg. This circular dependency will lock up flux. No error will be reported into the flux.ini file, but the last few lines will be talking about the PDA. Something like this:
The simple circular dependency is easy to notice and fix, but it gets harder to track down when you have 40 to 60 active packages. This kind of linker forces you to use strict hierarchy, where higher level layers call down into lower level layers, but lower levels never call up to higher layers.
There are a few useful tools for breaking the dependencies:
Use global variables to pass information between packages. Or attach object properties to items and share information this way. (This technique is normally avoided, but it can be your only choice.) So the guard package could directly reference an object property on the station to learn the kind of guards it should build.
Use "Task.Call" and "Task.Start" to invoke the function you need. Sometimes it is just impossible not to make a call from a lower layer back up to a higher layer. Because these two calls cannot take standard arguments, you need to use an argument passing convention like the one that starts this forum thread.
The station package could use Task.Call to start the guard code, creating a handle property on the task handle that contains the station it would like guards placed around. The guard code could then call the station code safely without circular link.
The best fix is to use pure hierarcy. A new package is defined called StationDefense.pkg. It calls the station package, and the guard package. The station package no longer needs to call the guard package. And the guard package is free to call the station package. The station package is lowest in the hierarcy, the guard package in the middle, and the StationDefense at the top.
-Gtrout
The POG linker cannot handle circular dependency between pog packages. This can happen very easily. Say you have a station.pkg
that gets called when the player arrives near a station. The station.pkg calls guard.pkg to create some guards for the station. The guard.pkg calls back to the station.pkg to find out what kind of station it is (so it can pick the proper kind of guards).
station.pkg calls guard.pkg. Guard.pkg call station.pkg. This circular dependency will lock up flux. No error will be reported into the flux.ini file, but the last few lines will be talking about the PDA. Something like this:
Code:
SCRIPT: [unknown] SPMainPDAScreen_OnStart: No test package specified - using normal game package "iPrelude"SPMainPDAScreen_OnStart: Starting story package "iPrelude"
The simple circular dependency is easy to notice and fix, but it gets harder to track down when you have 40 to 60 active packages. This kind of linker forces you to use strict hierarchy, where higher level layers call down into lower level layers, but lower levels never call up to higher layers.
There are a few useful tools for breaking the dependencies:
Use global variables to pass information between packages. Or attach object properties to items and share information this way. (This technique is normally avoided, but it can be your only choice.) So the guard package could directly reference an object property on the station to learn the kind of guards it should build.
Use "Task.Call" and "Task.Start" to invoke the function you need. Sometimes it is just impossible not to make a call from a lower layer back up to a higher layer. Because these two calls cannot take standard arguments, you need to use an argument passing convention like the one that starts this forum thread.
The station package could use Task.Call to start the guard code, creating a handle property on the task handle that contains the station it would like guards placed around. The guard code could then call the station code safely without circular link.
The best fix is to use pure hierarcy. A new package is defined called StationDefense.pkg. It calls the station package, and the guard package. The station package no longer needs to call the guard package. And the guard package is free to call the station package. The station package is lowest in the hierarcy, the guard package in the middle, and the StationDefense at the top.
-Gtrout
Please Log in or Create an account to join the conversation.
- GrandpaTrout
- Topic Author
- Offline
- King of Space
20 years 6 months ago #9786
by GrandpaTrout
Replied by GrandpaTrout on topic Cool Pog Tricks
I find that actual crashes to desktop are rare when writing script. Normally the script dies, but the game keeps running. There are some exceptions, and it is helpful to know of them when you are debugging crashes or lock up problems.
iSim.FindByNameInSystem. If you pass in junk strings to this function, you can sometimes crash the game to desktop. Make sure to only search for items you know exist. Which can be hard in a game where the player is supposed to blow things up.
String.FormatInt. If you hand in an invalid format string (say missing the %d) you can crash the system. Because this function is often used in debugging it is easy to be looking for one problem, and accidentally add a crash with your debug hunting code. All the String.Format calls may have this issue.
Keypress functions, or Button press functions: Some function are always executed in an atomic manner. Meaning that no other code will run until the function finishes. Keypress functions are like this. It is easy to lock up the game by writing functions that loop waiting for something to happen (which never will because no other code can run). Or functions that take a long time to finish. The way to get around this is to start a new task with Task.Detach(start new_task). This allows your task to wait, or do time consuming calculation without locking up the game.
Atomic functions are also used for deathscripts, and some of the early Multimod calls, like EnterSpace.
-Gtrout
iSim.FindByNameInSystem. If you pass in junk strings to this function, you can sometimes crash the game to desktop. Make sure to only search for items you know exist. Which can be hard in a game where the player is supposed to blow things up.
String.FormatInt. If you hand in an invalid format string (say missing the %d) you can crash the system. Because this function is often used in debugging it is easy to be looking for one problem, and accidentally add a crash with your debug hunting code. All the String.Format calls may have this issue.
Keypress functions, or Button press functions: Some function are always executed in an atomic manner. Meaning that no other code will run until the function finishes. Keypress functions are like this. It is easy to lock up the game by writing functions that loop waiting for something to happen (which never will because no other code can run). Or functions that take a long time to finish. The way to get around this is to start a new task with Task.Detach(start new_task). This allows your task to wait, or do time consuming calculation without locking up the game.
Atomic functions are also used for deathscripts, and some of the early Multimod calls, like EnterSpace.
-Gtrout
Please Log in or Create an account to join the conversation.
20 years 4 months ago #10678
by MajorTom
A quick way to crash the game due to interdependencies is in the application of "uses"
Say you have a GUI function that should pass information back to the script calling it:
my_script "uses" GuiFunction_script. That works fine but if you put my_script in the "uses" section of GuiFunction_script the game will crash every time when the linker tries to load: without the slightest indication why
Iwar2 Multiplayer Fan Site
Replied by MajorTom on topic Cool Pog Tricks
Originally posted by GrandpaTrout
The POG linker cannot handle circular dependency between pog packages.
-Gtrout
I find that actual crashes to desktop are rare when writing script. Normally the script dies, but the game keeps running. There are some exceptions, and it is helpful to know of them when you are debugging crashes or lock up problems.
A quick way to crash the game due to interdependencies is in the application of "uses"
Say you have a GUI function that should pass information back to the script calling it:
my_script "uses" GuiFunction_script. That works fine but if you put my_script in the "uses" section of GuiFunction_script the game will crash every time when the linker tries to load: without the slightest indication why
Iwar2 Multiplayer Fan Site
Please Log in or Create an account to join the conversation.
19 years 1 month ago #13699
by Digited
Replied by Digited on topic Cool Pog Tricks
Is there a way to get source code of some iw2 scripts? (iEscort, iFight, iFormation, iLagrangePoint, iWingman and some others) I don't need SDK's headers, but the code logic. No commercial use, of course.
Please Log in or Create an account to join the conversation.