JacobJ 10 Posted June 12, 2011 Hey all I have problems with my point-system. At the beginning of the mission I have a triggerarea that counts all the civilians in it and put a addeventhandler to each of them. I have delayed this counting of the civilians about 30sec to ensure that all the civilians has spawned. I have a limit of 50 civilians in the main city and they all spawn (some die falling from roffs and stuff, but totally 50 spawns). Now the question is, will the dead once spawn again to fill up the city to 50 or is the module a once-spawning system? I have tried to debug and it doesnt look so, but I have only tested it, with me in the game and maybe more players in the city will add up the civilians? Can I somehow make a trigger that activates as soon as all civilians have spawned (and a delay from there)? /Jacob Share this post Link to post Share on other sites
demonized 16 Posted June 12, 2011 (edited) the civilians is added dynamically i think, also based on your range from a major city or something, here is a easy snippet you can paste in a trigger on act field to count how many civilians are alive and how many have died, to debug. _null = [] spawn { _dead = 0; while {true} do { _alive = 0; _list = []; { if ((side _x) == civilian) then {_list = _list + [_x]}; } foreach allUnits; { if (alive _x) then {_alive = _alive + 1} else {_dead = _dead + 1; _list = _list - [_x]}; } foreach _list; hint format["alive civs is %1 --- dead civs is %2",_alive,_dead]; sleep 1; if ( ({alive _x AND (side _x) == civilian} count allUnits) != (count _list) ) then { { if (!alive _x) then {_dead = _dead + 1}; } foreach _list; }; }; }; ---------- Post added at 10:49 AM ---------- Previous post was at 10:45 AM ---------- oops, i pasted wrong part in post, left out side check, its fixed now. Edited June 12, 2011 by Demonized Share this post Link to post Share on other sites
JacobJ 10 Posted June 12, 2011 Okay thank you very much. The problem is tho, that I need the population of civilians to be stable, so that I can base a point-system on it and as far as I can see and with my little knowledge of scripting your code is displaying how many civilians are alive and dead each second, but the population can still rise causing the point-system to fail, because it will subtract points each time the difference between the starting population and the "new" population increases. Is it somehow possible to disable the auto-add-civilian feature and the range feature, so all civilians will be in the city all the time, wether or not any players are present? Share this post Link to post Share on other sites
demonized 16 Posted June 12, 2011 unfortunately youre wrong, because my code is counting dead and alive units, and when they are dead they are added to the count, also it counts if list of alive is changed from current allUnits and then rechecks and adds those to the count, so my snippet shows this: 1: at any time how many civilian units is alive at present. 2: how many civilians have died since mission start or start of script. easy way for you to test it is to place a few civilians, then spawn in some more civilians and see if numbers change, also go on rampage and kill some and spawn some more.... try testing before dismissing. for the module itself i cannnot help, but you should ask in the civilian module thread because thats where all the info is, also do search first in that thread. Share this post Link to post Share on other sites
JacobJ 10 Posted June 12, 2011 Okay I see, now I understand. My scripting knowledge let me down once again. Well your script is exactly what I need. I will work it into my points system and see how it works and then I will report back. Thank you for your help /Jacob Share this post Link to post Share on other sites
JacobJ 10 Posted June 13, 2011 Demonized, will this code run local or global? Can I remove the "_"'s and thereby make it global and use the publicVariable function to broadcast the values of the alive and dead list to all clients in a MP game? Share this post Link to post Share on other sites
demonized 16 Posted June 13, 2011 No you cannot simply remove the _ because alive is a command used by the gameengine, you need to make it something special, for example using your nick or something else. take out the hint part and make _alive,_dead into global variables by changing to: My_Global_Alive,My_Global_dead, broadcast those two variables with publicvariable and have another script run on each client to give hint: if (isServer) exitWith {}; waitUntil { !isNil "My_Global_Alive" AND !isNil "My_Global_dead" }; while {true} do { _alive = My_Global_Alive; _dead = My_Global_dead; hint format["alive civs is %1 --- dead civs is %2",_alive,_dead]; // here wait for the publicvariable to change then go to top and repeat hint. waitUntil { _alive != My_Global_Alive AND _dead != My_Global_dead }; }; remove the alive if you dont need it, i think you see how it works, if not just ask. edit: try this in a trigger placed in editor, it runs the count on serverside(dedicated or SP) only, and broadcasts any changes to the clients . _null = [] spawn { if (isDedicated) exitWith {}; waitUntil { !isNil "My_Global_Alive" AND !isNil "My_Global_dead" }; while {true} do { _alive = My_Global_Alive; _dead = My_Global_dead; hint format["alive civs is %1 --- dead civs is %2",_alive,_dead]; waitUntil { _alive != My_Global_Alive AND _dead != My_Global_dead }; }; }; _null = [] spawn { if (!isDedicated) exitWith {}; _dead = 0; My_Global_Alive = 0; My_Global_dead = 0; while {true} do { _alive = 0; _list = []; { if ((side _x) == civilian) then {_list = _list + [_x]}; } foreach allUnits; { if (alive _x) then {_alive = _alive + 1} else {_dead = _dead + 1; _list = _list - [_x]}; } foreach _list; if (My_Global_Alive != _alive OR My_Global_dead != _dead) then { My_Global_Alive = _alive; My_Global_dead = _dead; publicVariable "My_Global_Alive"; publicVariable "My_Global_dead"; }; sleep 1; if ( ({alive _x AND (side _x) == civilian} count allUnits) != (count _list) ) then { { if (!alive _x) then {_dead = _dead + 1}; } foreach _list; }; }; }; Share this post Link to post Share on other sites
JacobJ 10 Posted June 13, 2011 I have put this into a trigger activated by anyone: nul = [] execVM "script1.sqf"; I have pasted the code in your spoiler in the script1.sqf, but It doesnt come up with the hint. hmm is this because it wont start up in the editor and I have to export it to multiplayer and start a server to test this? Share this post Link to post Share on other sites
demonized 16 Posted June 13, 2011 well, it is probably a error somewhere in the code, as i used isDedicated on purpose so it should work if you tested also in Single player editor... will look into this later tonight, try replacing isDedicated with isServer, i will look into this more closely later tonight, i have no real time to test atm. Share this post Link to post Share on other sites
JacobJ 10 Posted June 13, 2011 (edited) Okay, thanks for the advice, I will try that out. ---------- Post added at 18:27 ---------- Previous post was at 16:43 ---------- I have tried putting in the isServer instead, but no change. Ive tried to play around with the first one you posted, but I get some very odd numbers out of this: cyw = 0; publicVariable "cyw"; _null = [] spawn { _dead = 0; while {true} do { _alive = 0; _list = []; { if ((side _x) == civilian) then {_list = _list + [_x]}; } foreach allUnits; { if (alive _x) then {_alive = _alive + 1; _x addEventHandler ["killed", {_unit = _this select 0; _killer = _this select 1; if (side _killer != west) exitWith {}; cyw = cyw + 1; publicVariable "cyw";}]} else {_dead = _dead + 1; _list = _list - [_x]}; } foreach _list; hint str cyw; sleep 1; if ( ({alive _x AND (side _x) == civilian} count allUnits) != (count _list) ) then { { if (!alive _x) then {_dead = _dead + 1}; } foreach _list; }; }; }; When I shoot a civilian, it counts to ect. 15. The next one it counts up to for example 36 and so on. Why will this code I have added not count up one at a time when a civilian gets shot? ---------- Post added at 18:51 ---------- Previous post was at 18:27 ---------- Okay I have now tried to narrow the code down to this: cyw = 0; while {true} do { { if ((side _x) == civilian) then {_x addEventHandler ["killed", {_unit = _this select 0; _killer = _this select 1; if (side _killer != west) exitWith {}; cyw = cyw + 1; publicVariable "cyw";}]}; } foreach allUnits; hint str cyw; sleep 1; }; Still it is giving me odd numbers like first 3, then 10, then 19 and so on. This code I have narrowed it down to is basicly what I need, but I need it to add 1 to the cyw variable as soon as a civilian gets shot. I just can't see why this is not working. First the code looks at allunits and narrow it down to civilians, then it puts an eventhandler in each of the civilians init and as soon as they gets killed, they add 1 to the variable cyw. Simple, but it doenst work... Edit: Hmm is it somehow possible that each time the loop is running, each civilian gets a new eventhandler to it? So if there has past 3 seconds, each civilian has 3 eventhandlers and therefore counts 3 up? Edited June 13, 2011 by JacobJ Share this post Link to post Share on other sites
demonized 16 Posted June 13, 2011 its because you add multiple eventhandlers on top of each other, so you count many times for same unit. try using setVAriable to seperate those already added. try this: cyw = 0; while {true} do { { if ((side _x) == civilian AND _x getVariable ["counted", true]) then { _x setVariable ["counted", false, true]; _x addEventHandler ["killed", { _unit = _this select 0; _killer = _this select 1; if (side _killer != west) exitWith {}; cyw = cyw + 1; publicVariable "cyw";}]}; } foreach allUnits; hint str cyw; sleep 1; }; Share this post Link to post Share on other sites
JacobJ 10 Posted June 13, 2011 That surely did the trick. Thank you very much, it works just as supposed to!! Without your help I wouldnt have been able to come so far, I am very grateful. ---------- Post added at 19:29 ---------- Previous post was at 19:14 ---------- Hmm, ive tested it now and it all works fine, but when I get to 5 counts, it stops counting. Isnt that weird? ---------- Post added at 19:38 ---------- Previous post was at 19:29 ---------- Every single time it stops at 5 counts... I thought variables could hold all the numbers in the world... ---------- Post added at 19:58 ---------- Previous post was at 19:38 ---------- Okay, ive played a bit with this now and it seems that it isnt specific 5 it can count to, it is a specific time it allows dead civilians to be counted in. So if I am very fast, I can kill more and if I wait it wont count up if I kill a civilian. Its as soon as I enter the city where civilians are it starts "counting down" and when the time has elapsed, it wont add anymore to the cyw variable. If I spawn far away and teleport to the city, it will let me kill and add to the cyw variable, but only just as long time as if I were spawning in the city. Is this a bug in ALICE or is there something wrong with the coding that leads to this problem? Share this post Link to post Share on other sites
demonized 16 Posted June 13, 2011 that was strange indeed, i tested witout civilian module, just placed a bunch of civvis on map, it stops at 5 in a few seconds..... so it is in the script not the civilian module. Share this post Link to post Share on other sites
JacobJ 10 Posted June 13, 2011 So you have the same problem as I do? Isnt it true, that this shouldnt happen and that the code seems more than fine? I have looked at it very long, but can't see where the holdup should be. Share this post Link to post Share on other sites
Muzzleflash 108 Posted June 13, 2011 Put this in your ALICE (Ambient Civilians) modules init: cyw = 0; publicVariable "cyw"; [bIS_alice_mainscope,"ALICE_civilianinit",[{ _this addEventHandler ["killed", { _killer = _this select 1; if (side _killer != west) exitWith {}; cyw = cyw + 1; }; }]] call bis_fnc_variablespaceadd; And use this loop instead: waitUntil {cyw > 0}; while {true} do { _oldCyw = cyw; publicVariable "cyw"; waitUntil {sleep 2; _oldCyw != cyw}; }; DISCLAIMER: this was written from memory. Share this post Link to post Share on other sites
demonized 16 Posted June 14, 2011 (edited) yeah, i tried different variations, took away the publicvariable, changed name.. one thing i found was this though: http://community.bistudio.com/wiki/Ambient_Civilians ALICE_civilianinit = <array>; - array of codes which is executed upon every civilian unit created.*snip* edit: seems muzzleflash already posted that code, i still couldnt get the thing to work with the civilian module init. anywho, screw this, i switched the civilians for opfor and it worked fine. but for civilians it wont work properly, i have not tried the civilian module init thing i quoted above though. the killed eventhandler does not like civilians... but i know that there are domination games with exactly that, killed civilians, but if they are just counting the dead and not using eventhandlers then that explains it, and we are back to using arrays and counts like the script in my first posts. edit: just to make sure i did add the eventhandler manually to every unit in their init field not using any fancy codes, then copied up 10 civilians with same eventhandler, killed them one by one in different tempo, count stopped at 5, always, did same with opfor units, count working fine everytime, counting up to 10. so its not the script, its something to do with civilians, civilian module has nothing to do with it. Edited June 14, 2011 by Demonized Share this post Link to post Share on other sites
JacobJ 10 Posted June 14, 2011 Okay, thank you Muzzelflash, I will try that out and see if I can get it working. Its a strange bug or what is the conclusion? If the code muzzleflash posted doesnt work, what then if I go back and use the first code you posted Demonized and make the _dead = cyw; That would work wouldnt it? The only problem is, that when I leave the city, the civ module kills all the civs (except 1 or 2, which I don't know why they have to live). The problem is also, that some civs spawn on roffs and high spots and when they see trouble the run for their lifes and that means killing themselfs falling from the roffs. So either the script has to be delayed a curtain time (which isnt bulletproff) or the civs has to be forced down to the ground, which put us back to the civ_init... Share this post Link to post Share on other sites
Muzzleflash 108 Posted June 14, 2011 There was a syntax error in my late night posting yester(to)day. This goes to the module's init (ALICE(1) or ALICE2 works both): cyw = 0; publicVariable "cyw"; [this,"ALICE_civilianinit",[{ _this addEventHandler ["killed", { _killer = _this select 1; if (side _killer != west) exitWith {}; cyw = cyw + 1; }]; }]] call bis_fnc_variablespaceadd; This could be an example of your loop (could also be done by a trigger): //You might wanna add a: // if (!isServer) exitWith {}; waitUntil {cyw > 0}; while {true} do { _oldCyw = cyw; //Tell players publicVariable "cyw"; //Tell here hint format ["Civ murders: %1", cyw]; waitUntil {sleep 2; _oldCyw != cyw}; }; If you only use the server to keep counts you can use [nil, nil, rHint, "My Message Here"] call RE; To write a message to all players, including if the server is also a player (host server). That requires the Functions module, however, that is automatically created by the ALICE module if you haven't done it yourself. All of this was tested this time. Happy mission making :). Share this post Link to post Share on other sites
JacobJ 10 Posted June 14, 2011 Your version works too, but only to 5 civilian kills. Then it stops counting and the hint fades out alltho I keep shooting civilians... Have you managed to kill more than 5 civilians and keep it counting up like say over 10 dead civs? ---------- Post added at 09:36 ---------- Previous post was at 09:31 ---------- Is there someway to check what a unit has in its init field or if the unit has an eventhandler? If so, it could be checked if the eventhandler just didnt get added to the unit or if it is someplace else we have to look for a solution. Any of you, know a mission that has something like this running and working? Share this post Link to post Share on other sites
Muzzleflash 108 Posted June 14, 2011 (edited) Damn can't believe I was so slow. The problem is obvious: When you go around killing civilians your rating drops. When your rating gets below -2000 you are hostile to all and no longer 'west'. It takes about 5 kills: http://community.bistudio.com/wiki/ArmA:_Rating_Values As you can see you start with 0 as a private and lose 400 per civilian kill. One solution is to add the following trigger I used to solve this exact same problem: Condition: local player On Act: 0 = [] spawn { while {true} do { _currentRating = rating player; if (_currentRating != 500000) then { player addRating (500000 - _currentRating); }; sleep (60*20); }; }; This runs a script resets immediately and every 20 minutes the players rating to 500000. You have to work damn fast to burn off that amount of rating. Edited June 14, 2011 by Muzzleflash Made it respawn safe Share this post Link to post Share on other sites
JacobJ 10 Posted June 14, 2011 Indeed that did the trick. Not in a million years I would have thought of that! Thank you very much! Now for others, Demonized's script should also work now, just remember the rating-issue as mentioned by Muzzleflash. Demonized's script works on all civilians, placed by editor or placed by ALICE. Muzzleflash's script only works for ALICE placed civs, but I think its a bit less power-consuming for the server the mission runs on i think.. Thank you both for helping me out with this! Share this post Link to post Share on other sites
demonized 16 Posted June 14, 2011 When you go around killing civilians your rating drops. When your rating gets below -2000 you are hostile to all and no longer 'west'. It takesah that explains it, i ripped out a few hairs on this.yeah the eventhandler way is the best way to go for acurate readings. about the process usage, im not sure what does most impact, i doubt you will see any difference in both ways. Share this post Link to post Share on other sites