Forum Jump :

Author Message

Foffy  



Posts: 4
Rank:


Level: Member

Country: us
Location:
Occupation:
Age:
In-game name:

 
#1 Posted at 2016-06-30 00:22        
     
Hey friends. Sorry if what I am asking is a mondo dumb and simple thing, but I figure I would ask here if one can help me with my likely silly issue.

Right now, I use to use ACE3 and have the AI engage in healing efforts, but the base mod itself doesn't allow this. However, someone on the BI forums posted a script and it appears to be a variation of Bardosy's Automedic script. I'll post it below.

// ai medic using ACE3
#include "\z\ace\addons\medical\script_component.hpp"
private ["_needradio", "_medic", "_injured", "_deads"];
_medic = _this select 0;
_units = _this select 1;
_injured = objNull;
_needradio = true;

//main loop
while {alive _medic} do {

sleep 2;
//waiting for a wounded
while {(isNull _injured) and (alive _medic)} do {
//if the medic is injured
if (_medic getvariable [QGVAR(isBleeding), false]) then {
//if medic is already dead, then exit
if (!alive _medic) exitWith{};
//else he is the injured and he is a priority to heal himself
_injured = _medic;
} else {
_deads = [];
{
if (!alive _x or isNull _x) then {
_deads = _deads + [_x];
};
if ((isNull _injured) and (_x getvariable [QGVAR(isBleeding), false]) and (alive _x) and (!isNull _x)) then {
_injured = _x;
if (_needradio) then {_medic groupChat format["Keep calm %1, I will heal you.", (name _injured)];};
};
} foreach _units;
_units = _units - _deads;
};
sleep 5;
};

if(!alive _medic) exitWith{};

//we have an injured, stop him
if ((!isPlayer _injured) and (_medic!=_injured)) then {
_injured disableAI "MOVE";
_injured setUnitPos "down";
};
if (_medic != _injured) then {
//medic go for him
_medic doMove (position _injured);
while {(_medic distance _injured > 10) and (alive _injured) and (!isNull _injured)} do {
sleep 1;
_medic doMove (position _injured);
if(!alive _medic) exitWith{_injured enableAI "MOVE"; _injured setUnitPos "auto";};
};
};

if(!alive _medic) exitWith{_injured enableAI "MOVE"; _injured setUnitPos "auto";};

//when medic is close enough to the injured...
//...and injured is still alive
if ((alive _injured) and (!isNull _injured) and (alive _medic)) then {
//stop the medic
// _medic disableAI "MOVE";
// _medic setUnitPos "middle";
// sleep 1;
//HEAL the injured
// ******************************
_medic allowDamage false;
_medic action ["HealSoldier", _injured];
_medic playMove "AinvPknlMstpSnonWnonDnon_medic_1";
sleep 9;
_injured setVariable [QGVAR(pain), 0, true];
_injured setVariable [QGVAR(morphine), 0, true];
_injured setVariable [QGVAR(bloodVolume), 100, true];
_injured setVariable ["ACE_isUnconscious", false, true];
_injured setvariable [QGVAR(tourniquets), [0,0,0,0,0,0], true];
_injured setvariable [QGVAR(openWounds), [], true];
_injured setvariable [QGVAR(bandagedWounds), [], true];
_injured setVariable [QGVAR(internalWounds), [], true];
_injured setvariable [QGVAR(lastUniqueWoundID), 1, true];
_injured setVariable [QGVAR(heartRate), 80];
_injured setvariable [QGVAR(heartRateAdjustments), []];
_injured setvariable [QGVAR(bloodPressure), [80, 120]];
_injured setVariable [QGVAR(peripheralResistance), 100];
_injured setVariable [QGVAR(fractures), [], true];
_injured setvariable [QGVAR(triageLevel), 0, true];
_injured setvariable [QGVAR(triageCard), [], true];
_injured setVariable [QGVAR(salineIVVolume), 0, true];
_injured setVariable [QGVAR(plasmaIVVolume), 0, true];
_injured setVariable [QGVAR(bloodIVVolume), 0, true];
_injured setvariable [QGVAR(bodyPartStatus), [0,0,0,0,0,0], true];
_injured setvariable [QGVAR(airwayStatus), 100];
_injured setVariable [QGVAR(airwayOccluded), false];
_injured setvariable [QGVAR(airwayCollapsed), false];
_injured setvariable [QGVAR(addedToUnitLoop), false, true];
_injured setvariable [QGVAR(inCardiacArrest), false, true];
_injured setvariable [QGVAR(hasLostBlood), 0, true];
_injured setvariable [QGVAR(isBleeding), false, true];
_injured setvariable [QGVAR(hasPain), false, true];
_injured setvariable [QGVAR(amountOfReviveLives), GVAR(amountOfReviveLives), true];
_injured setvariable [QGVAR(painSuppress), 0, true];
_injured setDamage 0;
// ******************************
//wait until injured is healed or dead
waitUntil { !(_injured getvariable [QGVAR(isBleeding), false]) or (!alive _injured) };
sleep 3;
if (_medic != _injured) then {
if (_needradio) then {_medic groupChat format["OK %1, you are ready to fight.", (name _injured)];};
};
_medic allowDamage true;
//healed soldier is ready to fight
_injured enableAI "MOVE";
_injured setUnitPos "auto";
};
//we are ready for looking a new injured
_injured = objNull;
//set the medic to ready to looking for a new injured
// _medic enableAI "MOVE";
// _medic setUnitPos "auto";
//doMove stops the medic, so we have to command him to follow his leader
_medic doFollow (leader group _medic);
if(!alive _medic) exitWith{_injured enableAI "MOVE"; _injured setUnitPos "auto";};
};


To my understanding, that allows medics and the AI to heal one another, so long as it is initialized on them. Here is the problem; I want something like this to be applied to all units upon the start of a mission, be it a custom mission I've made in the editor, an official mission from Bohemia, what have you. For that reason, I am unsure on how to apply this that generally, to make it apply to all units upon booting up a mission.

Would anyone be able to help me figure that out? I would appreciate it if one could.


Author Message


Posts: 29
Rank:


Level: Member

Country: de
Location: Berlin, Germany
Occupation:
Age:
In-game name:

 
#2 Posted at 2016-06-30 11:46        
     
In initServer.sqf do something like this:

fnc_handle_medic_script = compileFinal preprocessFileLineNumbers "yourscriptname.sqf"
{
 _side_unit = side _x;
 [_x, (allUnits select {side _x == _side_unit})] spawn fnc_handle_medic_script;
 true
} count (allUnits - allPlayers);
this applies ur medic script to each unit and orders it to heal each unit of its side.

You could do it this way to only order to heal all units of the group:
fnc_handle_medic_script = compileFinal preprocessFileLineNumbers "yourscriptname.sqf"
{
 [_x, (units _x)] spawn fnc_handle_medic_script;
 true
} count (allUnits - allPlayers);
this is much less performance eating as well.

Note: this has to be inserted in the initServer.sqf file of each mission where it should be active.
If u want to have a solution that works for every mission without adding code to its initServer.sqf then u ve to create ur own addon for it.
Idk how to do an addon and this is the wrong forum section to ask for it.

addon related topics can be created here:
FORUMS / Editing / Addon editing / Arma 3

This post was edited by sarogahtyp (2016-06-30 12:44, 1053 days ago)

Sarogahtyps Spawn Script Creator - SSSC
the easy way to cache ur units, vehicles and their waypoints

Advertisement


Author Message

Foffy  



Posts: 4
Rank:


Level: Member

Country: us
Location:
Occupation:
Age:
In-game name:

 
#3 Posted at 2016-06-30 12:51        
     
Thanks for the reply.

I am not sure if I am doing this right, though. I want to test this in the editor to see if I got all of this right, and I am getting nothing. I have used your first example of coding with my original post, and either it doesn't work, or I am making a mistake here. I then replaced that bit with the second but of coding you posted, and still no dice. I shoot one of my allies and he, nor the medic, do anything about it.

To specify, I have a folder named 'test', there's the initServer.sqf with your first example - the name of the sqf is "ACE_Autowounds.sqf" - and the name of the code from the first post is the same name. Nothing happens. What have I done wrong? I don't think ACE 3 is the issue, for the code I provided apparently can work if added to a unit. I want something where it's all-encompassing as a script without linking it to a specific unit.


Author Message


Posts: 29
Rank:


Level: Member

Country: de
Location: Berlin, Germany
Occupation:
Age:
In-game name:

 
#4 Posted at 2016-06-30 13:26        
     
post the error messages (if there r some) from the .rpt file please

open ur windows explorer and enter this into its adress line:

%userprofile%\AppData\Local\Arma 3

after hitting enter u r in the folder where the newest .rpt file is located.

maybe its a folder issue. the initServer.sqf has to be in ur missions root folder. it should look like this:
yourmissionname.altis/initServer.sqf


in which folder is the file ACE_Autowounds.sqf located? and is that the file where the code of ur first post is in?

Sarogahtyps Spawn Script Creator - SSSC
the easy way to cache ur units, vehicles and their waypoints

Author Message

Foffy  



Posts: 4
Rank:


Level: Member

Country: us
Location:
Occupation:
Age:
In-game name:

 
#5 Posted at 2016-06-30 13:43        
     
There are no errors in the rpt file, save for a scope one, which I assume is just ACE.

I have the initServer.sqf file in the same folder as the saved test. ACE_Autowounds.sqf is in the same folder, and contains all of the code the first post has.

I know the code works, as initializing it to a specific unit worked with the following code.

dummy = [this, units (group this)] execVM "ACE_Autowounds.sqf";

There are two problems I find in doing this.

- I want this to be auto-initialized by a script; I do not wish to add this to a unit in every mission by hand
- The above code (in the first post) kind of breaks if applied to more than one unit; if anyone could help me, I'd like to sparse out the self-aid part of the script. Otherwise, everyone literally becomes a medic for everyone else, and this fails at what I want. I want everyone to self-heal, and maybe give the medic an enhanced ability to consider healing others. Right now the above script treats everyone like a medic, as a group healer, when I want self healer to be the general priority. AGM used to have a system that matched what I am looking for, but that's no longer supported, and strangely omitted from ACE 3, its successor project...

I assume your code wasn't working because it may work with vanilla medics. I want this to work with ACE's enhanced medical system.


EDIT: I was able to trim the code in the first post to only work n the enabled unit, but perhaps someone can help me trim out the excess 'fat' that's no longer needed regarding reference to other units in its coding...


// ai medic using ACE3
#include "\z\ace\addons\medical\script_component.hpp"
private ["_needradio", "_medic", "_injured", "_deads"];
_medic = _this select 0;
_units = _this select 1;
_injured = objNull;
_needradio = true;

//main loop
while {alive _medic} do {

sleep 2;
//waiting for a wounded
while {(isNull _injured) and (alive _medic)} do {
//if the medic is injured
if (_medic getvariable [QGVAR(isBleeding), false]) then {
//if medic is already dead, then exit
if (!alive _medic) exitWith{};
//else he is the injured and he is a priority to heal himself
_injured = _medic;
} else {
_deads = [];
{
if (!alive _x or isNull _x) then {
_deads = _deads + [_x];
};
if ((isNull _injured) and (_x getvariable [QGVAR(isBleeding), false]) and (alive _x) and (!isNull _x)) then {	
_injured = _x;
};
}
};
sleep 5;
};

if(!alive _medic) exitWith{};

//we have an injured, stop him
if ((!isPlayer _injured) and (_medic!=_injured)) then {
_injured disableAI "MOVE";
_injured setUnitPos "down";
};
if (_medic != _injured) then {
//medic go for him
_medic doMove (position _injured);
while {(_medic distance _injured > 10) and (alive _injured) and (!isNull _injured)} do {	
sleep 1;
_medic doMove (position _injured);
if(!alive _medic) exitWith{_injured enableAI "MOVE"; _injured setUnitPos "auto";};
};
};

if(!alive _medic) exitWith{_injured enableAI "MOVE"; _injured setUnitPos "auto";};

//when medic is close enough to the injured...
//...and injured is still alive
if ((alive _injured) and (!isNull _injured) and (alive _medic)) then {	
//stop the medic
//	_medic disableAI "MOVE";
//	_medic setUnitPos "middle";
//	sleep 1;
//HEAL the injured
// ******************************
_medic action ["HealSoldier", _injured];
_medic playMove "AinvPknlMstpSnonWnonDnon_medic_1";
sleep 9;
_injured setVariable [QGVAR(pain), 0, true];
_injured setVariable [QGVAR(morphine), 0, true];
_injured setVariable [QGVAR(bloodVolume), 100, true];
_injured setVariable ["ACE_isUnconscious", false, true];
_injured setvariable [QGVAR(tourniquets), [0,0,0,0,0,0], true];
_injured setvariable [QGVAR(openWounds), [], true];
_injured setvariable [QGVAR(bandagedWounds), [], true];
_injured setVariable [QGVAR(internalWounds), [], true];
_injured setvariable [QGVAR(lastUniqueWoundID), 1, true];
_injured setVariable [QGVAR(heartRate), 80];
_injured setvariable [QGVAR(heartRateAdjustments), []];
_injured setvariable [QGVAR(bloodPressure), [80, 120]];
_injured setVariable [QGVAR(peripheralResistance), 100];
_injured setVariable [QGVAR(fractures), [], true];
_injured setvariable [QGVAR(triageLevel), 0, true];
_injured setvariable [QGVAR(triageCard), [], true];
_injured setVariable [QGVAR(salineIVVolume), 0, true];
_injured setVariable [QGVAR(plasmaIVVolume), 0, true];
_injured setVariable [QGVAR(bloodIVVolume), 0, true];
_injured setvariable [QGVAR(bodyPartStatus), [0,0,0,0,0,0], true];
_injured setvariable [QGVAR(airwayStatus), 100];
_injured setVariable [QGVAR(airwayOccluded), false];
_injured setvariable [QGVAR(airwayCollapsed), false];
_injured setvariable [QGVAR(addedToUnitLoop), false, true];
_injured setvariable [QGVAR(inCardiacArrest), false, true];
_injured setvariable [QGVAR(hasLostBlood), 0, true];
_injured setvariable [QGVAR(isBleeding), false, true];
_injured setvariable [QGVAR(hasPain), false, true];
_injured setvariable [QGVAR(amountOfReviveLives), GVAR(amountOfReviveLives), true];
_injured setvariable [QGVAR(painSuppress), 0, true];
_injured setDamage 0;
// ******************************
//wait until injured is healed or dead
waitUntil { !(_injured getvariable [QGVAR(isBleeding), false]) or (!alive _injured) };
sleep 3;

//healed soldier is ready to fight
_injured enableAI "MOVE";
_injured setUnitPos "auto";
};
//we are ready for looking a new injured
_injured = objNull;
//set the medic to ready to looking for a new injured
//	_medic enableAI "MOVE";
//	_medic setUnitPos "auto";
//doMove stops the medic, so we have to command him to follow his leader
_medic doFollow (leader group _medic);
if(!alive _medic) exitWith{_injured enableAI "MOVE"; _injured setUnitPos "auto";};
};

I am now able to get the general results I wanted in that when applied, the unit will only self-heal. But I still lack something to make this apply to all units so I do not have to initialize every one of them.

This post was edited by Foffy (2016-06-30 15:22, 1052 days ago)


Author Message


Posts: 29
Rank:


Level: Member

Country: de
Location: Berlin, Germany
Occupation:
Age:
In-game name:

 
#6 Posted at 2016-06-30 16:55        
     
I m sure that my above code should work and that it is independent from any mod.
It could be a timing problem, maybe ACE isnt initialized at the moment the code starts.
u could try somethimng like this:


waitUntil{sleep 0.5; BIS_fnc_init};
fnc_handle_medic_script = compileFinal preprocessFileLineNumbers "yourscriptname.sqf"
{
 [_x, (units _x)] spawn fnc_handle_medic_script;
 true
} count (allUnits - allPlayers);

Sarogahtyps Spawn Script Creator - SSSC
the easy way to cache ur units, vehicles and their waypoints

Author Message

Foffy  



Posts: 4
Rank:


Level: Member

Country: us
Location:
Occupation:
Age:
In-game name:

 
#7 Posted at 2016-07-01 00:43        
     
I was able to figure out how to make the code I posted apply to all units earlier, actually. :P

{[_x] execVM "ACE_automedic.sqf"} forEach allUnits;

A very simple init. However, as I largely got what I wanted - self-healing AI - I have two very complicated issues I have no idea on how to solve.

- Is there a way to somehow use the altered script I made in post 5 to give extra abilities to actual medics? Right now it works that upon every unit, they have the basic medical ability to self-heal. I was wondering if there was a way to make the medic class in-game somehow special, to give them additional healing potential.

- This code does not cause the unit to use their own ACE medical items, which potentially can break realism. Essentially, the code as it is allows infinite heals of the AI, and I have zero idea on how to make them actually use the bandages and morphine every unit is given at init in ACE; that code is essentially letting them heal values in an animation, but not use any item, making it an unlimited use situation. I get what I wanted on one hand, but I've now made the AI kind of OP in that so long as they are alive, they can heal themselves. I would greatly like someone to help me figure that out.

EDIT: A weird oddity I am finding with this script is that this also applies to me, as a human player. This means the game will actually stop me to do this. Now I guess I gotta figure out how to change that, too...

This post was edited by Foffy (2016-07-01 01:30, 1052 days ago)


Author Message


Posts: 29
Rank:


Level: Member

Country: de
Location: Berlin, Germany
Occupation:
Age:
In-game name:

 
#8 Posted at 2016-07-01 07:06        
     
your solution to apply it is the same I wrote before with the difference that u not precompile a function from the script. your method compiles the script everytime before it runs on each unit. in my version its only compiled once.
the other difference is that u use forEach instead of count which is slightly faster.
and at last u use allUnits instead of allUnits-allPlayers which causes ur problem that the script is applied to players as well.

to get extra abilities to the medic u could rollback to the original version of the script and insert a check if unit is a medic like this:
if(_medic getUnitTrait "Medic") then
{
 hint "its a medic";
}
else
{
 hint "its not a medic";
};

This post was edited by sarogahtyp (2016-07-01 09:07, 1052 days ago)

Sarogahtyps Spawn Script Creator - SSSC
the easy way to cache ur units, vehicles and their waypoints