Elementy nieobecne w tabeli i ich eliminacja

Edytor Arma (Arma, Arma2, Arma2OA)

Moderatorzy: kondor, Inkwizytor

ODPOWIEDZ
Awatar użytkownika
SaS TrooP
Posty: 1586
Rejestracja: 30 października 2008, 17:30
ID Steam:
ID gracza: 0
Lokalizacja: Wodzisław Śl.
Kontakt:

Elementy nieobecne w tabeli i ich eliminacja

Post autor: SaS TrooP »

Mam sobie tabelkę nie pisaną ręcznie, ale tworzoną z komendy:

Kod: Zaznacz cały

_company = units _banditgroup;
By następnie operować jej elementami za pomocą:

Kod: Zaznacz cały

_troop1 = (_company select 0);
_troop2 = (_company select 1);
_troop3 = (_company select 2);
_troop4 = (_company select 3);
_troop5 = (_company select 4);
_troop6 = (_company select 5);
_troop7 = (_company select 6);
Byłoby dobrze, tylko że grupa ma losowo od 2 do 7 osób w oddziale, a więc zmienne _troop3 do _troop7 mogą być nieaktywne. Gdy próbuję je wybrać naturalnie wywala błąd.
Chcę tym skryptem usuwać ciała poprzez:

Kod: Zaznacz cały

deletevehicle _troop1;
deletevehicle _troop2;
deletevehicle _troop3;
deletevehicle _troop4;
deletevehicle _troop5;
deletevehicle _troop6;
deletevehicle _troop7;
Więc w jaki sposób mam zapełnić ewentualne luki w tabeli? Mógłbym teoretycznie zależną if-then sprawdzać, czy poszczególne zmienne istnieją, ale w jaki sposób mam to robić? sprawdzać poprzez alive? Nie za bardzo mam pomysł jakich komend w typ przypadku użyć.


Edit: Próbowałem tak:

Kod: Zaznacz cały

_company = units _banditgroup;
_troop1 = (_company select 0);
_troop2 = (_company select 1);

if (!alive _troop3) then

{
    _troop3 = (_company select 2);
    
}

else

{
    
};

if (!alive _troop4) then

{
    _troop4 = (_company select 3);
    
}

else

{
    
};

if (!alive _troop5) then

{
    _troop5 = (_company select 4);
    
}

else

{
    
};

if (!alive _troop6) then

{
    _troop6 = (_company select 5);
    
}

else

{
    
};

if (!alive _troop7) then

{
    _troop7 = (_company select 6);
    
}

else

{
    
};
Ale nie działa.
Awatar użytkownika
kondor
Posty: 1526
Rejestracja: 13 marca 2007, 11:50
ID Steam: Przemek_kondor
Kontakt:

Re: Elementy nieobecne w tabeli i ich eliminacja

Post autor: kondor »

1. To o czym mówisz nazywa się tablica, nie tabela
2. Ten sposób na usuwanie ciał jest mocno "naokoło". Polecam:
a) dodać wszystkim jednostkom grupy eventhandler "killed" i w wywoływanym skrypcie usuwać ciało lub
b) użyć garbage-collector (pol.: śmieciarz, czy coś w tym stylu): http://community.bistudio.com/wiki/Garbage_Collector co jest wg mnie najprostsze i najelegantsze
3. wielkość grupy możesz badać tak:

Kod: Zaznacz cały

count units _banditgroup
4. Nie możesz badać:

Kod: Zaznacz cały

if (!alive _troop3) then
skoro nawet nic jeszcze nie podstawiłeś pod tą zmienną.
Awatar użytkownika
SaS TrooP
Posty: 1586
Rejestracja: 30 października 2008, 17:30
ID Steam:
ID gracza: 0
Lokalizacja: Wodzisław Śl.
Kontakt:

Re: Elementy nieobecne w tabeli i ich eliminacja

Post autor: SaS TrooP »

Problem polega na tym, że:

1. Skryptów jest bardzo dużo i wzywanie garbage collectora do każdego z AIków może być dość problematyczne. Poza tym testowałem to i odpalając teoretycznie prawidłowo GC (tj. przez init jednostki) nic się nie działo, nawet po oddaleniu na odpowiedni dystans.
2. Eventhandler byłby niezłym pomysłem, gdyby nie to, że część ciał powinna zostać. Są także wrogowie/sojusznicy, którzy nie respawnują się w kółko i ich znikanie byłoby także problematyczne.

Oba punkty potraktuję jako rozwiązania awaryjne. Źle zrobiłem nie pokazując całego skryptu. Obszedłem to co prawda samemu, ale jestem co najmniej nieprzekonany do tego rozwiązania, może być na dłuższą metę prawdopodobnie nieco procesożerne, a przynajmniej tak mi się wydaje, dlatego wciąż szukam rozwiązania:

Kod: Zaznacz cały

if (isNil { BIS_fnc_init }) then { waitUntil { !isNil { BIS_fnc_init } } }; 
 
private ["_squad","_member1","_member2","_member3","_member4","_member5","_member6","_member7","_soldier1","_soldier2","_soldier3","_soldier4","_soldier5","_soldier6","_soldier7","_banditgroup","_company"];
_squad = 
[
    "GUE_Soldier_AR",
    "GUE_Soldier_CO",
    "GUE_Soldier_Crew",
    "GUE_Soldier_GL",
    "GUE_Soldier_Sniper",
    "GUE_Soldier_MG",
    "GUE_Soldier_Medic",
    "GUE_Soldier_Pilot",
    "GUE_Soldier_3",
    "GUE_Soldier_2",
    "GUE_Soldier_1",
    "GUE_Soldier_AT",
    "GUE_Soldier_AA",
    "GUE_Soldier_Sab",
    "GUE_Soldier_Scout",
    "GUE_Commander"
];


_member1 = _squad call BIS_fnc_selectRandom;
_member2 = _squad call BIS_fnc_selectRandom;
_member3 = _squad call BIS_fnc_selectRandom;
_member4 = _squad call BIS_fnc_selectRandom;
_member5 = _squad call BIS_fnc_selectRandom;
_member6 = _squad call BIS_fnc_selectRandom;
_member7 = _squad call BIS_fnc_selectRandom;


_banditgroup = creategroup west;

sleep 1;
_soldier1= _member1 createUnit [getMarkerPos "logic_bandit_group1", _banditgroup,"arming = [this] execVM 'random_arm_hn.sqf'; nul=[this,'kurwamac'] execVM 'scripts\upsmon.sqf'; gadka = [this] execVM 'Dialog1start.sqf';", 0.5, "SERGEANT"];
sleep 0.1;
_soldier2 = _member2 createUnit [getMarkerPos "logic_bandit_group1", _banditgroup,"arming = [this] execVM 'random_arm_hn.sqf';", 0.5, "corporal"];
sleep 0.1;
_soldier3 = _member3 createUnit [getMarkerPos "logic_bandit_group1", _banditgroup,"arming = [this] execVM 'random_arm_hn.sqf';", 0.6, "corporal"];
sleep 0.1;
_soldier4 = _member4 createUnit [getMarkerPos "logic_bandit_group1", _banditgroup,"arming = [this] execVM 'random_arm_hn.sqf';", 0.5, "corporal"];
sleep 0.1;
_soldier5 = _member5 createUnit [getMarkerPos "logic_bandit_group1", _banditgroup,"arming = [this] execVM 'random_arm_hn.sqf';", 0.5, "corporal"];
sleep 0.1;
_soldier6 = _member6 createUnit [getMarkerPos "logic_bandit_group1", _banditgroup,"arming = [this] execVM 'random_arm_hn.sqf';", 0.5, "corporal"];
sleep 0.1;
_soldier7 = _member7 createUnit [getMarkerPos "logic_bandit_group1", _banditgroup,"arming = [this] execVM 'random_arm_hn.sqf';", 0.5, "corporal"];
sleep 0.1;

sleep 1;

_company = units _banditgroup;


sleep 5;

_troop1 = (_company select 0);
_troop2 = (_company select 1);
_troop3 = (_company select 2);
_troop4 = (_company select 3);
_troop5 = (_company select 4);
_troop6 = (_company select 5);
_troop7 = (_company select 6);

sleep 2;
if (random 100 > 50) then {deletevehicle _troop3};
if (random 100 > 50) then {deletevehicle _troop4};
if (random 100 > 50) then {deletevehicle _troop5};
if (random 100 > 50) then {deletevehicle _troop6};
if (random 100 > 50) then {deletevehicle _troop7};

sleep 1;
hint str (units _banditgroup);



sleep 3;
waitUntil {sleep 1;{alive _x} count units _banditgroup < 1};

sleep 7;

hint "dead, rspwn";

deletevehicle _troop1;
deletevehicle _troop2;
deletevehicle _troop3;
deletevehicle _troop4;
deletevehicle _troop5;
deletevehicle _troop6;
deletevehicle _troop7;


deletegroup _banditgroup;

hint "clear, srspwn in 10 sec";
sleep 10;
test = player execVM "random_squad.sqf";

Problem jest taki, że grupa może mieć od 3 do 7 osób, a tablica natychmiast wywala błąd i psuje skrypt, gdy wzywany element się w niej nie znajduje. Respawn jednostek _soldier3 do _soldier7 jest więc wątpliwy i nie mogę ich ręcznie dodać do tablicy.
Nie da się usuwać jednostek poprzez foreach units etc., dlatego tylko na czas tego skryptu muszę im przydzielić ich nazwy, na których będę operować, by móc po respawnie zastąpić je klonami. Jednak jeśli np. _soldier5 się nie pojawi, to jednocześnie nie ma elementu odpowiadającego _soldierowi5 w tablicy _company, więc wzywanie tego elementu poprzez select wyrzuca błąd. Muszę znaleźć metodę, która pozwoli więc albo nie okreslać _troop5 albo wkładać w jego miejsce cokolwiek innego, co następnie będzie przez skrypt ignorowane.
Możliwe, że to już nie ta godzina, ale nie widzę na razie zastosowania sensownego count units _banditgroup. Mógłbyś sprecyzować w jaki sposó to wykorzystać?

Myślę, że teraz też wyraziłem się nieco jaśniej, ponieważ pierwszy post może komplikować.
Awatar użytkownika
kondor
Posty: 1526
Rejestracja: 13 marca 2007, 11:50
ID Steam: Przemek_kondor
Kontakt:

Re: Elementy nieobecne w tabeli i ich eliminacja

Post autor: kondor »

1. garbage collector jest 1, więc nie jest "ciężki"
2. nie rozumiem
Porawiłem trochę skrypt, ale nie widzę usuwania ciał (ani za pomocą deleteVehicle ani hideBody):

Kod: Zaznacz cały

private ["_squad","_banditgroup","_company","_if","_rank","_markerPos","_groupSize","_initField","_sergeantInitField"];

// niepotrzebny byl "if" skoro waitUntil bada warunek
waitUntil {!isNil "bis_fnc_init"};

_squad =
[
    "GUE_Soldier_AR",
    "GUE_Soldier_CO",
    "GUE_Soldier_Crew",
    "GUE_Soldier_GL",
    "GUE_Soldier_Sniper",
    "GUE_Soldier_MG",
    "GUE_Soldier_Medic",
    "GUE_Soldier_Pilot",
    "GUE_Soldier_3",
    "GUE_Soldier_2",
    "GUE_Soldier_1",
    "GUE_Soldier_AT",
    "GUE_Soldier_AA",
    "GUE_Soldier_Sab",
    "GUE_Soldier_Scout",
    "GUE_Commander"
];

_banditgroup = creategroup west;
_markerPos = getMarkerPos "logic_bandit_group1";
_groupSize = 3 + (floor random 5); // to wylosuje liczbe z zakresu [3..7]
_initField = "arming = [this] execVM 'random_arm_hn.sqf';";
_sergeantInitField = "arming = [this] execVM 'random_arm_hn.sqf'; nul=[this,'kurwamac'] execVM 'scripts\upsmon.sqf'; gadka = [this] execVM 'Dialog1start.sqf';";

sleep 1;

// inicjalizacja
_company = [];

for "_i" from 1 to _groupSize do 
{
	_if = if (_i == 1) then {_sergeantInitField} else { _initField };
	_rank = if (_i == 1) then { "SERGEANT" } else { "corporal" };
	_company set [count _company, (_squad call BIS_fnc_selectRandom) createUnit [_markerPos, _banditgroup, _if, 0.5, _rank]];
	sleep 0.1;
};
sleep 7;
hint str (units _banditgroup);
sleep 3;
waitUntil {sleep 1;{alive _x} count units _banditgroup < 1};
sleep 7;
hint "dead, rspwn";

for "_i" from 0 to _groupSize do
{
	hideBody (_company select _i);
};
deletegroup _banditgroup;

hint "clear, srspwn in 10 sec";
sleep 10;
test = player execVM "random_squad.sqf";
Próbowałem też usuwanie robić w pętli forEach:

Kod: Zaznacz cały

{ deleteVehicle _x; } forEach _company;
ale wyskakuje błąd, że _x jest niezdefiniowany :o albo coś przeoczyłem, albo mam braki
Nie da się usuwać jednostek poprzez foreach units etc.,
Mógłbyś rozwinąć?
Awatar użytkownika
SaS TrooP
Posty: 1586
Rejestracja: 30 października 2008, 17:30
ID Steam:
ID gracza: 0
Lokalizacja: Wodzisław Śl.
Kontakt:

Re: Elementy nieobecne w tabeli i ich eliminacja

Post autor: SaS TrooP »

Dziś rozwinąłem skrypt samemu z pomocą Wolfruga, dało się to. Podsunięcie komendy isNil, bo właśnie takie efektu szukałem sprawia się nieźle :P
Co prawda była ona użyta w tym skrypcie, ale czasem potrzebuję po prostu tylko komendy i resztę mogę zrobić sam.

Kod: Zaznacz cały

Nie da się usuwać jednostek poprzez foreach units etc.,
Psułem ja, ponieważ usuwałem z grupy (podczas gry zabita jednostka jej z niej usuwana) zamiast z tablicy. Poprawione.

Mój skrypt, teraz działa:

Kod: Zaznacz cały

//////////////////////////////////////////////////////////////////
// Function file for Armed Assault
// Created by: SaS TrooP
//////////////////////////////////////////////////////////////////


if (isNil { BIS_fnc_init }) then { waitUntil { !isNil { BIS_fnc_init } } }; 
 
private ["_squad","_member1","_member2","_member3","_member4","_member5","_member6","_member7","_soldier1","_soldier2","_soldier3","_soldier4","_soldier5","_soldier6","_soldier7","_banditgroup","_company","_troop1","_troop2","_troop3","_troop4","_troop5","_troop6","_troop7"];
_squad = 
[
    "GUE_Soldier_AR",
    "GUE_Soldier_CO",
    "GUE_Soldier_Crew",
    "GUE_Soldier_GL",
    "GUE_Soldier_Sniper",
    "GUE_Soldier_MG",
    "GUE_Soldier_Medic",
    "GUE_Soldier_Pilot",
    "GUE_Soldier_3",
    "GUE_Soldier_2",
    "GUE_Soldier_1",
    "GUE_Soldier_AT",
    "GUE_Soldier_AA",
    "GUE_Soldier_Sab",
    "GUE_Soldier_Scout",
    "GUE_Commander"
];


_member1 = _squad call BIS_fnc_selectRandom;
_member2 = _squad call BIS_fnc_selectRandom;
_member3 = _squad call BIS_fnc_selectRandom;
_member4 = _squad call BIS_fnc_selectRandom;
_member5 = _squad call BIS_fnc_selectRandom;
_member6 = _squad call BIS_fnc_selectRandom;
_member7 = _squad call BIS_fnc_selectRandom;


_banditgroup = creategroup west;

sleep 1;
_soldier1= _member1 createUnit [getMarkerPos "logic_bandit_group1", _banditgroup,"arming = [this] execVM 'random_arm_hn.sqf'; nul=[this,'zone2_ups'] execVM 'scripts\upsmon.sqf';", 0.5, "SERGEANT"];
sleep 0.1;
_soldier2 = _member2 createUnit [getMarkerPos "logic_bandit_group1", _banditgroup,"arming = [this] execVM 'random_arm_hn.sqf';", 0.5, "corporal"];
sleep 0.1;
if (random 100 > 50) then {_soldier3 = _member3 createUnit [getMarkerPos "logic_bandit_group1", _banditgroup,"arming = [this] execVM 'random_arm_hn.sqf';", 0.6, "corporal"]};
sleep 0.1;
if (random 100 > 50) then {_soldier4 = _member4 createUnit [getMarkerPos "logic_bandit_group1", _banditgroup,"arming = [this] execVM 'random_arm_hl.sqf';", 0.5, "corporal"]};
sleep 0.1;
if (random 100 > 50) then {_soldier5 = _member5 createUnit [getMarkerPos "logic_bandit_group1", _banditgroup,"arming = [this] execVM 'random_arm_hn.sqf';", 0.5, "corporal"]};
sleep 0.1;
if (random 100 > 50) then {_soldier6 = _member6 createUnit [getMarkerPos "logic_bandit_group1", _banditgroup,"arming = [this] execVM 'random_arm_hn.sqf';", 0.5, "corporal"]};
sleep 0.1;
if (random 100 > 50) then {_soldier7 = _member7 createUnit [getMarkerPos "logic_bandit_group1", _banditgroup,"arming = [this] execVM 'random_arm_hn.sqf';", 0.5, "corporal"]};
sleep 0.1;

sleep 1;

_company = units _banditgroup;


sleep 5;

_troop1 = (_company select 0);
_troop2 = (_company select 1);

if (!isNil "_soldier3") then {_troop3 = (_company select 2)};
if (!isNil "_soldier4") then {_troop4 = (_company select 3)};
if (!isNil "_soldier5") then {_troop5 = (_company select 4)};
if (!isNil "_soldier6") then {_troop6 = (_company select 5)};
if (!isNil "_soldier7") then {_troop7 = (_company select 6)};


sleep 2;

sleep 1;
hint str (units _banditgroup);



sleep 3;
waitUntil {sleep 1;{alive _x} count units _banditgroup < 1};

sleep 180;

hint "dead, rspwn";

{deletevehicle _x} foreach _company;

sleep 120;

deletegroup _banditgroup;

hint "clear, srspwn in 10 sec";
sleep 10;
test = player execVM "random_squad_bn1.sqf";




Wydaje mi siętakże wydajny, ale poprawę parę rzeczy, które mi podałeś.
Awatar użytkownika
kondor
Posty: 1526
Rejestracja: 13 marca 2007, 11:50
ID Steam: Przemek_kondor
Kontakt:

Re: Elementy nieobecne w tabeli i ich eliminacja

Post autor: kondor »

Główny problem, który masz w tym skrypcie to koncept rozmiaru grupy, który najpierw tworzy maksymalną liczbę, a później losowo je usuwa, zamiast po prosu stworzyć losową liczbę osób.
PS0: Niepotrzebne są też w ogóle zmienne _soldierN czy _troopN. Czym więcej masz zmiennych tym trudniej nad nimi później zapanować.
PS1: Poza tym dobrze jeśli nazwy zmiennych wskazują co zawierają. Np _squad i _memberN wskazują raczej na kolejno grupę i jednostkę, podczas gdy zawierają tablicę klas i klasę.
PS2: Jeśli kod się powtarza, rozważ użycie pętli lub funkcji.
ODPOWIEDZ

Wróć do „Edycja oraz tworzenie misji, skrypty oraz programowanie”