It looks like the 'text="Server";' thing is working correctly; I had it hint if it was the server, and it did--the client didn't print anything. However, I have made poor assumptions about what is communicated across machines. This has all been very strange.
To recap: I have a script that repositions all the players using a random base position. I use this on the playable squad, and all AI-controlled players will be repositioned together. If the server is also a player, that player is repositioned with them. However, all other human players are not repositioned. This happens if I run the code in init.sqs.
Now let's say I create a trigger in the mission that immediately evaluates to true when the mission starts. When activated, it calls the repositioning code. It tests to make sure it only runs on the server. This code moves the whole squad--human and AI--together correctly. However, it takes a moment to activate, which makes it seem like we're being warped from one place to another in the game.
So how does this all work anyhow? I believe I can use public variables to get the updated positions for each player. It's tedious, but I think it's necessary, and I'll deal with it. However, what about:
- Updated enemy waypoints
- Manual orders to enemy units
- event handles for weapon firing placed on all players
If this all runs in the init.sqs, and I have it only run on the server, am I in trouble? That code is much harder to test.
Edit: I just discovered the magic of public variables, and it still doesn't make any sense. What seems to happen is the positions of clients just cannot be changed with the code I have. One problem is I don't really know where to use publicvariable -- does it go up top and get declared on client and servers? Do I call it every time I change a noteworthy variable? I don't really know. Let me just paste a ton of code:
;publicvariable "rescue_pos1_x"
;publicvariable "rescue_pos1_y"
;publicvariable "rescue_pos2_x"
;publicvariable "rescue_pos2_y"
;publicvariable "rescue_pos3_x"
;publicvariable "rescue_pos3_y"
;publicvariable "rescue_pos4_x"
;publicvariable "rescue_pos4_y"
;publicvariable "rescue_pos5_x"
;publicvariable "rescue_pos5_y"
;publicvariable "rescue_pos6_x"
;publicvariable "rescue_pos6_y"
;publicvariable "rescue_pos7_x"
;publicvariable "rescue_pos7_y"
;publicvariable "rescue_pos8_x"
;publicvariable "rescue_pos8_y"
;publicvariable "rescue_pos9_x"
;publicvariable "rescue_pos9_y"
;publicvariable "rescue_pos10_x"
;publicvariable "rescue_pos10_y"
;publicvariable "rescue_pos11_x"
;publicvariable "rescue_pos11_y"
;publicvariable "prepared"
; Have one pilot dead (nonplayable)
DeadPilot setDammage 1.0
; Start up the chopper
(crew RescueChopper select 0) action ["Engine on", RescueChopper]
?!local Server: goto "ClientCode"
; For transmitting all updated player positions to the clients
; Arrays cannot be transmitted, so we have to be very tedious about this
rescue_pos1_x = 0
rescue_pos1_y = 0
rescue_pos2_x = 0
rescue_pos2_y = 0
rescue_pos3_x = 0
rescue_pos3_y = 0
rescue_pos4_x = 0
rescue_pos4_y = 0
rescue_pos5_x = 0
rescue_pos5_y = 0
rescue_pos6_x = 0
rescue_pos6_y = 0
rescue_pos7_x = 0
rescue_pos7_y = 0
rescue_pos8_x = 0
rescue_pos8_y = 0
rescue_pos9_x = 0
rescue_pos9_y = 0
rescue_pos10_x = 0
rescue_pos10_y = 0
rescue_pos11_x = 0
rescue_pos11_y = 0
; When 1, all the initial conditions for random positioning have been prepared
prepared = 0;
publicvariable "prepared"
VictoryConditions = 0
_crash_site = [0.0, 0.0]
randomly_position = preprocessFile "randomly_position.sqf"
fired_marker = preprocessFile "fired_marker.sqf"
marker_fired = 0
marker_shooter = objnull;
;_marker_fired = [[0, 1, 2, 3, "Flare"]] call fired_marker
Rescue1 addEventHandler ["fired", format[ { marker_fired = marker_fired + ([_this] call fired_marker), marker_shooter=_this select 0 }]]
Rescue2 addEventHandler ["fired", format[ { marker_fired = marker_fired + ([_this] call fired_marker), marker_shooter=_this select 0 }]]
Rescue3 addEventHandler ["fired", format[ { marker_fired = marker_fired + ([_this] call fired_marker), marker_shooter=_this select 0 }]]
Rescue4 addEventHandler ["fired", format[ { marker_fired = marker_fired + ([_this] call fired_marker), marker_shooter=_this select 0 }]]
Rescue5 addEventHandler ["fired", format[ { marker_fired = marker_fired + ([_this] call fired_marker), marker_shooter=_this select 0 }]]
Rescue6 addEventHandler ["fired", format[ { marker_fired = marker_fired + ([_this] call fired_marker), marker_shooter=_this select 0 }]]
Rescue7 addEventHandler ["fired", format[ { marker_fired = marker_fired + ([_this] call fired_marker), marker_shooter=_this select 0 }]]
Rescue8 addEventHandler ["fired", format[ { marker_fired = marker_fired + ([_this] call fired_marker), marker_shooter=_this select 0 }]]
Rescue9 addEventHandler ["fired", format[ { marker_fired = marker_fired + ([_this] call fired_marker), marker_shooter=_this select 0 }]]
Rescue10 addEventHandler ["fired", format[ { marker_fired = marker_fired + ([_this] call fired_marker), marker_shooter=_this select 0 }]]
Rescue11 addEventHandler ["fired", format[ { marker_fired = marker_fired + ([_this] call fired_marker), marker_shooter=_this select 0 }]]
; place an infantry squad near the crash site so the rescue squad doesn't get much breathing time.
_crash_site = [[Rescue1, Rescue2, Rescue3, Rescue4, Rescue5, Rescue6, Rescue7, Rescue8, Rescue9, Rescue10, Rescue11, HeliWreck, DeadPilot], CrashBoundTL, CrashBoundBR] call randomly_position
rescue_pos1_x = (getPos Rescue1) select 0
publicvariable "rescue_pos1_x"
rescue_pos1_y = (getPos Rescue1) select 1
publicvariable "rescue_pos1_y"
hint format["Rescue 1 pos %1 %2", rescue_pos1_x, rescue_pos1_y]
rescue_pos2_x = (getPos Rescue2) select 0
publicvariable "rescue_pos2_x"
rescue_pos2_y = (getPos Rescue2) select 1
publicvariable "rescue_pos2_y"
rescue_pos3_x = (getPos Rescue3) select 0
publicvariable "rescue_pos3_x"
rescue_pos3_y = (getPos Rescue3) select 1
publicvariable "rescue_pos3_y"
rescue_pos4_x = (getPos Rescue4) select 0
publicvariable "rescue_pos4_x"
rescue_pos4_y = (getPos Rescue4) select 1
publicvariable "rescue_pos4_y"
rescue_pos5_x = (getPos Rescue5) select 0
publicvariable "rescue_pos5_x"
rescue_pos5_y = (getPos Rescue5) select 1
publicvariable "rescue_pos5_y"
rescue_pos6_x = (getPos Rescue6) select 0
publicvariable "rescue_pos6_x"
rescue_pos6_y = (getPos Rescue6) select 1
publicvariable "rescue_pos6_y"
rescue_pos7_x = (getPos Rescue7) select 0
publicvariable "rescue_pos7_x"
rescue_pos7_y = (getPos Rescue7) select 1
publicvariable "rescue_pos7_y"
rescue_pos8_x = (getPos Rescue8) select 0
publicvariable "rescue_pos8_x"
rescue_pos8_y = (getPos Rescue8) select 1
publicvariable "rescue_pos8_y"
rescue_pos9_x = (getPos Rescue9) select 0
publicvariable "rescue_pos9_x"
rescue_pos9_y = (getPos Rescue9) select 1
publicvariable "rescue_pos9_y"
rescue_pos10_x = (getPos Rescue10) select 0
publicvariable "rescue_pos10_x"
rescue_pos10_y = (getPos Rescue10) select 1
publicvariable "rescue_pos10_y"
rescue_pos11_x = (getPos Rescue11) select 0
publicvariable "rescue_pos11_x"
rescue_pos11_y = (getPos Rescue11) select 1
publicvariable "rescue_pos11_y"
prepared = 1
publicvariable "prepared"
;hint format["prepared is %1", prepared]
; The first responders will be randomly placed in a diagonal direction from the crash site.
_rand_x = random 2
_rand_x = _rand_x - (_rand_x mod 1)
_rand_y = random 2
_rand_y = _rand_y - (_rand_y mod 1)
_responders_pos = [((_crash_site select 0) + 100.0 * _rand_x - 200.0), ((_crash_site select 1) + 100.0 * _rand_y - 200.0)]
{_x setPos _responders_pos} forEach units FirstResponders
; Initial orders
; Move all the SOD waypoints to the crash site
[CaptureCar, 2] SetWPPos _crash_site
[CaptureCrew, 2] SetWPPos _crash_site
[PrisonerCar, 1] SetWPPos _crash_site
[FirstResponders, 1] SetWPPos _crash_site
[ProwlingShilka, 1] SetWPPos _crash_site
[Mi17_Spotter, 1] SetWPPos _crash_site
[North_Squad, 1] SetWPPos [(_crash_site select 0) + random(200) - 100.0, (_crash_site select 1) + random(200) - 100.0]
[South_Squad, 1] SetWPPos [(_crash_site select 0) + random(200) - 100.0, (_crash_site select 1) + random(200) - 100.0]
[East_Squad, 1] SetWPPos [(_crash_site select 0) + random(200) - 100.0, (_crash_site select 1) + random(200) - 100.0]
[West_Squad, 1] SetWPPos [(_crash_site select 0) + random(200) - 100.0, (_crash_site select 1) + random(200) - 100.0]
; Pick a "Sasser Squad." Randomly pick from one or more of all the controlled East troops in this mission,
; and override their orders with orders to attack the rescue group at all times. This means it will be updated
; every time the command loop finishes. It's hardly fair, but tons more fun. We'll use the SOD waypoints for all
; units -- this allows any boarded APCs to unload before their sassing begins
_array_picker = random 10
_array_picker = _array_picker - (_array_picker mod 1)
_sasser_waypoint = [[CaptureCar, 2], [CaptureCrew, 2], [PrisonerCar, 1], [FirstResponders, 1], [ProwlingShilka, 1], [North_Squad, 1], [South_Squad, 1], [East_Squad, 1], [West_Squad, 1], [Mi17_Spotter, 1]] select _array_picker
; Commander's loop. This code acts like a commander making decisions to all the east's resources available for
; tracking and killing this opponent.
#CommandLoop
; Has a flare been detected? If so, send a helicopter towards it.
if(marker_fired > 0) then { Mi17_flare_hunter move position marker_shooter, Mi17_flare_hunter setCombatMode "RED", Mi17_flare_hunter commandTarget marker_shooter}
; Updating the sasser squads to the exact coordinates of the downed crew
_sasser_waypoint SetWPPos (getPos leader Downed_Squad)
[FirstResponders, 1] SetWPPos (getPos leader Downed_Squad)
~5
; Check if the victory conditions are met:
; 1. All downed crew that are alive are in the chopper
; 2. The chopper is near the landing base
#VictoryCheck
; Check if the victory conditions are met:
; 1. All downed crew that is alive is in the chopper
; 2. They chopper is near the landing base
#VictoryCheck
VictoryConditions = 0
?alive Rescue1 && !(Rescue1 in RescueChopper) : goto "CommandLoop"
?alive Rescue2 && !(Rescue2 in RescueChopper) : goto "CommandLoop"
?alive Rescue3 && !(Rescue3 in RescueChopper) : goto "CommandLoop"
?alive Rescue4 && !(Rescue4 in RescueChopper) : goto "CommandLoop"
?alive Rescue5 && !(Rescue5 in RescueChopper) : goto "CommandLoop"
?alive Rescue6 && !(Rescue6 in RescueChopper) : goto "CommandLoop"
?alive Rescue7 && !(Rescue7 in RescueChopper) : goto "CommandLoop"
?alive Rescue8 && !(Rescue8 in RescueChopper) : goto "CommandLoop"
?alive Rescue9 && !(Rescue9 in RescueChopper) : goto "CommandLoop"
?alive Rescue10 && !(Rescue10 in RescueChopper) : goto "CommandLoop"
?alive Rescue11 && !(Rescue11 in RescueChopper) : goto "CommandLoop"
VictoryConditions = 1
goto "CommandLoop"
#ClientCode
;@prepared == 1
hint format["Rescue1 position %1 %2", rescue_pos1_x, rescue_pos1_y]
@prepared == 1
Rescue1 setPos [rescue_pos1_x, rescue_pos1_y]
Rescue2 setPos [rescue_pos2_x, rescue_pos2_y]
Rescue3 setPos [rescue_pos3_x, rescue_pos3_y]
Rescue4 setPos [rescue_pos4_x, rescue_pos4_y]
Rescue5 setPos [rescue_pos5_x, rescue_pos5_y]
Rescue6 setPos [rescue_pos6_x, rescue_pos6_y]
Rescue7 setPos [rescue_pos7_x, rescue_pos7_y]
Rescue8 setPos [rescue_pos8_x, rescue_pos8_y]
Rescue9 setPos [rescue_pos9_x, rescue_pos9_y]
Rescue10 setPos [rescue_pos10_x, rescue_pos10_y]
Rescue11 setPos [rescue_pos11_x, rescue_pos11_y]
What I've tested is having server as Rescue2, and client as Rescue3. On both machines, it will claim Rescue1 is at the default location, not one generated by the random placement function. If I make the server Rescue1, it will be randomly assigned, and both machines will print the correct location. If make the client Rescue1, it will be at the default location and both servers will agree. It just seems like I can't make the client budge. How the hell can that be?