Home   Help Search Login Register  

Author Topic: Rank function - Help needed  (Read 2523 times)

0 Members and 1 Guest are viewing this topic.

Offline h-

  • OFPEC Site
  • Administrator
  • *****
  • Formerly HateR_Kint
    • OFPEC
Rank function - Help needed
« on: 11 Sep 2004, 18:06:14 »
Well, after a relentless testing (amongst the whirlwind of MCAR developement) I've managed to dig up a way of determining the rank given for a unit in the mission editor. So, this function would most probably be called getRank then ::)...

Now, you may ask yourselves what's the use for this function.. ::)
I asked it myself and found no pleasing answer really ;D...
Other than some AI scripts and/or CoC AI on Demand style deleteVehicle/re-createVehicle scripts...

Anyway, I've almost cracked up this thing, but the problem seems to be the vehicles...
In OFP, the rank given to any vehicle is given to the vehicles driver, the next higher rank is given to the gunner, and the next higher to the commander...
Now, obviously, the getRank should then return the drivers rank, but it seems that what ever I do the wrong rank is returned, usually one higher than the drivers actual rank or just PRIVATE or that really annoying 'scalar puiwpiopwueru' error...
For some reason I just can' get this stuff sorted, and as you see, there's a way in the code (one out of many) I've tried to use but with no luck...

So what he function would now need is a way of detecting whether the passed unit is a vehicle and if so, then 'treating' all the crew and cargo inside it so that the rank can be attained from then if they for example exit the vehicle... Which the cargo will most likely do at some point...

I've attached the function to this post...
I also quote the code below...

Read carefully the usage instructions from the .sqf itself (the attached file outdated, don't use...) before using, it's a bit tricky... (and too long to quote here...)

Code: [Select]
private ["_all","_unit","_task","_mkunit","_mk_ratU","_mkratUx","_rank","_ratU","_ratUx","_ratUm"];
_all    = _this select 0;
_unit   = vehicle (_this select 1);
_task   = _this select 2;

if (_task != "mark_htr" && _task != "rank_htr")
 then
    {
     hint format ["ERROR!!\nTask -> %1 <- not regocnised!\nUse only 'mark_htr' or 'rank_htr'.",_task];
     _rank = "<null>";
    };

if (_task == "mark_htr")
 then
    {
     _cnt      = count _all;
     _mkratU   = 0;
     _mkratUx  = 0;
     _i        = 0;

     while "_i <= _cnt"
       do
        {
     _mkunit = _all select _i;
     if ("Man" countType [_mkunit] < 1)
          then
         {
      _mkunit = (driver _mkunit);
         };
         _mkratUx = rating _mkunit;

     _mkunit addRating _mkratUx - (_mkratUx * 2);
         _mkratU = _mkratUx / 10000;
     _mkunit addRating (_mkratUx + (_mkratU / 2)) + 10;

     _i = _i + 1;
      };
  };


if (_unit in _all && alive _unit)
 then
    {
      _ratUx = rating _unit;
   if ("Man" countType [_unit] < 1)
        then
       {
        _ratUx = rating (driver _unit);
       };
   if (_ratUx < 0 && _ratUx > -2000)
        then
       {
        _ratUx = abs _ratUx;
       };
      _ratUm = _ratUx - (_ratUx mod 1);
      _ratU = ((_ratUx - _ratUm) * 10000) + random 3;
      _ratU = _ratU * 2;

   if (_ratU >= 7500)
    then {_rank = "COLONEL";};

   if (_ratU >= 5000 && _ratU < 7500)
    then {_rank = "MAJOR";};

   if (_ratU >= 3500 && _ratU < 5000)
    then {_rank = "CAPTAIN";};

   if (_ratU >= 2500 && _ratU < 3500)
    then {_rank = "LIEUTNANT";};

   if (_ratU >= 1500 && _ratU < 2500)
    then {_rank = "SERGEANT";};

   if (_ratU >= 500 && _ratU < 1500)
    then {_rank = "CORPORAL";};

   if ((_ratU >= 0 && _ratU < 500))
    then {_rank = "PRIVATE";};
    }
   else
      {
   if ((rating _unit) > -2000 && alive _unit)
    then
       {
        hint format ["ERROR!!\n%1 not in the given array!",_unit];
        _rank = "<null>";
       };
   if ((rating _unit) <= -2000 && alive _unit)
    then {_rank = "RENEGADE TREASENOUS BASTARD!!!!";};
      };

_rank

And I sure hope General Barron doesn't show up saying 'oh, I did this too already' ;) ;D ;D ::)
« Last Edit: 17 Sep 2004, 18:39:32 by HateR_Kint »
Project MCAR   ---   Northern Fronts   ---   Emitter 3Ditor
INFORMATIVE THREAD TITLES PLEASE. "PLEASE HELP" IS NOT ONE..
Chuck Norris can divide by zero.

Offline sim

  • Members
  • *
  • Hot! Real hot! Damn Hot!
Re:Rank function - Help needed
« Reply #1 on: 11 Sep 2004, 22:07:15 »
wow, looks quite.... complicated, lol.  ::)

I'll have to give it a try.

Quote
And I sure hope General Barron doesn't show up saying 'oh, I did this too already'

He probably will, he always does  :P

sim
The Unsung Campaign Team Leader

Offline General Barron

  • Former Staff
  • ****
  • Semper Fi!
Re:Rank function - Help needed
« Reply #2 on: 12 Sep 2004, 05:22:29 »
[shadow=red,left,300]I DID THIS TOO ALREADY!!![/shadow]  :P ::)
[/size][/font][/color]

Lol... just kidding. :P Nah, I knew you could find the unit's rank at the start of a mission by looking at its rating, but the idea of "storing" that rank in the unit's rating is very clever indeed.

Now, I haven't looked at the code too in depth yet, and I haven't tried it in game, but I get the general idea of it. First off, these parts confuse me:

Code: [Select]
    _mkunit addRating _mkratUx - (_mkratUx * 2);
         _mkratU = _mkratUx / 10000;
     _mkunit addRating (_mkratUx + (_mkratU / 2)) + 10;
... .... .. .. . ... ..
      _ratUm = _ratUx - (_ratUx mod 1);
      _ratU = ((_ratUx - _ratUm) * 10000) + random 3;
      _ratU = _ratU * 2;
Is that the "crappy/weird 'maths like' " stuff you are talking about? I understand the first line, but the next two are.... very, very strange, unless I just don't get it. ??? Well, you say that OFP does some weird stuff with long decimal numbers. This could be because of the way floating point numbers work on a binary level: they are limited to a fixed number of digits. So the more digits in front of the decimal, the less digits can be behind the decimal, and the computer has to round. So maybe when the unit gains more score, then things start getting screwed up.

Just a possibility, I guess. But perhaps it would help to do this:
   Private -> rating + 0.1
   Corporal -> rating + 0.2
   Sergeant -> rating + 0.3
And so on and so forth.  That way there are less numbers after the decimal to get messed up with OFP's 'fuzzy math'.


As for your problem with vehicles, I don't have a very good answer. All I know is I don't really understand how vehicles work in scripts, when it isn't an empty vehicle that had units moved into it. That's why I never even place manned vehicles anymore (just an empty one and then moveindriver someone) :crazy:. But I have some thoughts.... basically, you shouldn't use the "driver" command for vehicles, because some vehicles have no driver (eg, m2 machine guns). I think the "crew" command would be better (returns an array of everybody in the vehicle). That way you can 'mark' everybody in the vehicle, and also 'read' everybody in the vehicle.


Okay, a few more comments on the script. First off, it appears to do the "rank" routine even when you call the script for the "mark" routine. That's just a waste of resources, which could be a big drain at the start of the map with lots of units.
Also, why on earth should it be called with the "nil" in the middle of the parameters? Why not make the unit (where the nil goes) the very last parameter, and then only check that parameter when you are doing the "rank" routine. You could also get rid of the whole "rank_htr"/"mark_htr" string: just make it do the "rank" routine if a unit has been passed, otherwise it does the "mark" routine. For example:

[array, <unit>] call getRank

_array = _this select 0
if (count _this > 1) then {_unit = _this select 1; do rank routine}
else {do mark routine}
« Last Edit: 12 Sep 2004, 05:28:29 by General Barron »
HANDSIGNALS COMMAND SYSTEM-- A realistic squad-control modification for OFP
kexp.org-- The best radio station in the world, right here at home! Listen to John Richards!

Offline h-

  • OFPEC Site
  • Administrator
  • *****
  • Formerly HateR_Kint
    • OFPEC
Re:Rank function - Help needed
« Reply #3 on: 12 Sep 2004, 07:26:10 »
Quote
Is that the "crappy/weird 'maths like' " stuff you are talking about? I understand the first line, but the next two are....
;D
Actually, even I can't remember why I had to do it like that.. ::)
_mkunit addRating _mkratUx - (_mkratUx * 2); -> changes the units rating to 0
_mkratU = _mkratUx / 10000; -> original rating 'taken' from the unit is put below the decimal, so it's now 0000.xxxx, and stored into a variable...
_mkunit addRating (_mkratUx + (_mkratU / 2)) + 10;  -> Now, this actually confuses me too ;D but this was the only way I could add the rating to the unit, so that it includes the unitsRating.initialRating...

The other math bit just reverses that above action... Weirdly, but does it anyway... :P
I absolutely suck in maths so that's probably the reason why these are so confusing...
_ratUm = _ratUx - (_ratUx mod 1); -> this should 'even' up the rating (above the decimal of course) to make it 'zeroable'...
_ratU = ((_ratUx - _ratUm) * 10000) + random 3; -> the above decimal value is first 'zeroed' and then divided by 10000 to get the below decimal value... It can be done this way as OFP can understand only the above decimal value... the random 3 adds a random value at the end to compensate that 'OFP oddity on long floating points' stuff...
_ratU = _ratU * 2; -> well, this shows that there's something wrong in some of the above 'maths' as the gained value needs to be multiplied by two in order for it to be correct... :P ::)
Altough, this was not needed when I was first testing this, I needed to add this later on, about the same time I started the vehicle testing...
Because at one point I could retrieve the drivers rating, but below decimal rating was always half of the actual rating, so I just added that line there...
If there's somebody who has a better way of completing this, please share... :P

Quote
So maybe when the unit gains more score, then things start getting screwed up
May be, altough There was no problems with the score gained, but then again, I never tested it so that it would have gone over 10000...

But, I think OFP works so that you can have 6 digits above the decimal and 6 below, so this should stay pretty stable if thinking like that... ???

Quote
Just a possibility, I guess. But perhaps it would help to do this:
  Private -> rating + 0.1
  Corporal -> rating + 0.2
  Sergeant -> rating + 0.3
And so on and so forth.  That way there are less numbers after the decimal to get messed up with OFP's 'fuzzy math'.
Could be, altough I would still need some of the fuzzy stuff to actually put that below the decimal ;D :P

Quote
That's why I never even place manned vehicles anymore (just an empty one and then moveindriver someone)
I do this too quite a lot, only when I'm sure I will not be scripting the vehicle into anything, I place the 'original' filled unit...
But usually I manage to funk up the mission when every single object on the map is somehow scripted ::)

Quote
But I have some thoughts.... basically, you shouldn't use the "driver" command for vehicles, because some vehicles have no driver (eg, m2 machine guns). I think the "crew" command would be better
Trust me, I have tried crew too, in many many many (*commandant Lazard voice*) different ways...
The driver is currently there just to keep the stuff working on men so I can prove it works on some level...

Quote
just make it do the "rank" routine if a unit has been passed, otherwise it does the "mark" routine. For example
Yeah, good point... I'll add that...

Altough, this is just a 'rough' code, I usually start the optimizing when the code works otherwise...

Quote
First off, it appears to do the "rank" routine even when you call the script for the "mark" routine
This code is actually a bit earlier version that I currently had, but the current had so much 'confusement' in it that it just didn't work, so I reverted back to a version that works which of course has less stuff in it than the one that stopped working altogether...
This version indeed runs both the routines but will not when I get the vehicle part working...
Project MCAR   ---   Northern Fronts   ---   Emitter 3Ditor
INFORMATIVE THREAD TITLES PLEASE. "PLEASE HELP" IS NOT ONE..
Chuck Norris can divide by zero.

Unnamed

  • Guest
Re:Rank function - Help needed
« Reply #4 on: 12 Sep 2004, 07:46:44 »
Hi,

To test for vehicles just use:

Code: [Select]
If ((Vehicle Player)!=Player) Then {Hint Format ["Player is in a %1",Typeof (vehicle Player)]}
Quote
_ratU = _ratU * 2; -> well, this shows that there's something wrong in some of the above 'maths' as the gained value needs to be multiplied by two in order for it to be correct...

Is'nt all that to compensate for ratings less then 0? I think rating becomes negative when you team kill or something.

But as long as it works and the original rating is stored back in OFP, then I would not worry about :)

Offline h-

  • OFPEC Site
  • Administrator
  • *****
  • Formerly HateR_Kint
    • OFPEC
Re:Rank function - Help needed
« Reply #5 on: 12 Sep 2004, 08:13:43 »
Quote
To test for vehicles just use:
;D
I know that...

But in this case it won't help because this needs to work on AI too...
And as the thisList from a trigger won't differentiate vehicles from men (a vehicle is single unit (and a group of 1-3)... A man is single unit (and a group of 1)...) so vehicle _unit != _unit won't work...

I have also tried various methods of "vehicleType" countType [_unit] > 0...

Quote
Is'nt all that to compensate for ratings less then 0? I think rating becomes negative when you team kill or something.
Yeah, and if it goes down to -2000 or less, you are a 'renegade'...

Quote
But as long as it works and the original rating is stored back in OFP, then I would not worry about
Quite :D

@GB:
Quote
the idea of "storing" that rank in the unit's rating is very clever indeed
Quite, but as I say in the function comments (or do I?) this is not my idea, somebody posted about how OFP only reads the above decimal stuff from the rating a long time ago here at OFPEC...

The downside in this is that if someone uses this same method on something else, this and the other script(s) get screwed up...
« Last Edit: 12 Sep 2004, 08:15:05 by HateR_Kint »
Project MCAR   ---   Northern Fronts   ---   Emitter 3Ditor
INFORMATIVE THREAD TITLES PLEASE. "PLEASE HELP" IS NOT ONE..
Chuck Norris can divide by zero.

Unnamed

  • Guest
Re:Rank function - Help needed
« Reply #6 on: 12 Sep 2004, 09:18:03 »
Quote
And as the thisList from a trigger won't differentiate vehicles from men

I see, ThisList should just return pointers to objects. The problem is, you dont know the pointer of the driver, to make the comparison.

But if I understand it properly, you can do it this way:

Code: [Select]
(vehicle ((Crew s1) Select 0))!=((Crew s1) Select 0)
That will return true if it's a manned AI vehicle or false if it's just an AI soldier. You can test to see if it's an empty vehicle using IsNull. The crew command always returns an array of AI men, even if it's used on a soldier.

I guess a soldier's body is just considered a vehicle for the AI. Which is quite philosophical, for a computer game.
« Last Edit: 12 Sep 2004, 09:19:56 by Unnamed »

Offline h-

  • OFPEC Site
  • Administrator
  • *****
  • Formerly HateR_Kint
    • OFPEC
Re:Rank function - Help needed
« Reply #7 on: 12 Sep 2004, 09:29:57 »
Quote
I see, ThisList should just return pointers to objects
Quite, I was not sure if should use a 'real coding' terms, such as pointer... :P

Quote
The problem is, you dont know the pointer of the driver, to make the comparison.
It would need a pointer into a pointer ::)

Quote
But if I understand it properly, you can do it this way
Hmm...
Will test that...

Makes me wonder why oh why I always seem to miss the obvious... ::)
But with my luck, even that does not work...

Quote
I guess a soldier's body is just considered a vehicle for the AI.
Which is true, as all soldiers lye in the class CfgVehicles...
It's just the simulations that make the difference...

Quote
Which is quite philosophical, for a computer game.
;D ;D
Indeed...
So, to keep this philosophical there's always the old saying:
'It's not the class, it's the simulation that counts'... ::)
Project MCAR   ---   Northern Fronts   ---   Emitter 3Ditor
INFORMATIVE THREAD TITLES PLEASE. "PLEASE HELP" IS NOT ONE..
Chuck Norris can divide by zero.

Offline h-

  • OFPEC Site
  • Administrator
  • *****
  • Formerly HateR_Kint
    • OFPEC
Re:Rank function - Help needed
« Reply #8 on: 12 Sep 2004, 11:32:23 »
Quote
_array = _this select 0
if (count _this > 1) then {_unit = _this select 1; do rank routine}
else {do mark routine}
Ok, how exactly is this supposed to work???

I tried this, and if there's no element in the calling array ([array] call getRank) the _this select 1 returns the "scalar bool...."

So, I then made a sentence if (_this select 1 == "scalar bool....") then {do mark stuff} else {do rank stuff}
The mark stuff won't run at all ( ??? ) which is totally weird, and then when the _this select 1 has a value ([array,unit] call getRank) the if (_unit == "scalar bool....") then .... gives a error message, and the |#| is situated after the then operator, so it suggests it's the 'General error in expression'...
And of course the rank then returns the "scalar bool....."...

So then used [array,""] call getRank, and made if (_this select 1 == ""} then {....}....
With exactly the same results, only now the "mark" stuff runs...
But still when using a unit instead of "" the if {_this select 1 == "") then {...} gives that same error message as above and of course the "rank" part won't run...

I have never used if/then/else in OFP succesfully, so I try to avoid it to the last breath...
For me the else{} only works if it has only one or two arguments in it, the other usually being exit ::) (in .sqs of course...)

Here's the code now, but it will be changing...:
Code: [Select]
private ["_all","_unit","_mkunit","_mk_ratU","_mkratUx","_rank","_ratU","_ratUx","_ratUm"];
_all    = _this select 0;
_unit    = _this select 1;

if (_unit == "") then
{
     _cnt      = count _all;
     _mkratU   = 0;
     _mkratUx  = 0;
     _i        = 0;

     while "_i <= _cnt"
       do
        {
     _mkunit = _all select _i;
     _mkratUx = rating _mkunit;
   
     _mkunit addRating _mkratUx - (_mkratUx * 2);
     _mkratU = _mkratUx / 10000;
     _mkunit addRating (_mkratUx + (_mkratU / 2)) + 10;

     _i = _i + 1;
    };
}
else
{
   _ratUx = rating _unit;
    if (_ratUx < 0 && _ratUx > -2000)
        then
       {
        _ratUx = abs _ratUx;
       };
      _ratUm = _ratUx - (_ratUx mod 1);
      _ratU = ((_ratUx - _ratUm) * 10000) + random 3;
      _ratU = _ratU * 2;

   if (_ratU >= 7500)
    then {_rank = "COLONEL";};

   if (_ratU >= 5000 && _ratU < 7500)
    then {_rank = "MAJOR";};

   if (_ratU >= 3500 && _ratU < 5000)
    then {_rank = "CAPTAIN";};

   if (_ratU >= 2500 && _ratU < 3500)
    then {_rank = "LIEUTNANT";};

   if (_ratU >= 1500 && _ratU < 2500)
    then {_rank = "SERGEANT";};

   if (_ratU >= 500 && _ratU < 1500)
    then {_rank = "CORPORAL";};

   if ((_ratU >= 0 && _ratU < 500))
    then {_rank = "PRIVATE";};

   if (!(_unit in _all))
    then
       {
        hint format ["ERROR!!\n%1 not in the given array!",_unit];
        _rank = "<null>";
       };
   if ((rating _unit) <= -2000 && alive _unit)
    then {_rank = "RENEGADE TREASENOUS BASTARD!!!!";};
    };

_rank
Project MCAR   ---   Northern Fronts   ---   Emitter 3Ditor
INFORMATIVE THREAD TITLES PLEASE. "PLEASE HELP" IS NOT ONE..
Chuck Norris can divide by zero.

Unnamed

  • Guest
Re:Rank function - Help needed
« Reply #9 on: 12 Sep 2004, 13:07:12 »
Quote
I have never used if/then/else in OFP succesfully, so I try to avoid it to the last breath...
For me the else{} only works if it has only one or two arguments in it, the other usually being exit  (in .sqs of course...)

If you initalize _unit in {}'s. It wont be available to the rest of the script. Try this:

Code: [Select]
_unit=ObjNull
if (count _this > 1) then {_unit = _this select 1; do rank routine}

I prefer if then's, but probably easier done with:

Code: [Select]
? (count _this > 1) : _unit = _this select 1
P.S Same with exit, it would just exit the code contained in the {}.

Offline h-

  • OFPEC Site
  • Administrator
  • *****
  • Formerly HateR_Kint
    • OFPEC
Re:Rank function - Help needed
« Reply #10 on: 12 Sep 2004, 16:49:20 »
Quote
If you initalize _unit in {}'s. It wont be available to the rest of the script.
Right, absolutely totally forgot about that... >:(

But, if you take a look at the quoted code, the _unit is initialized outside the first {}...

Quote
Same with exit, it would just exit the code contained in the {}
Oh??
Well, in sqf however exit does absolutely nothing...
No matter where you put it...
Project MCAR   ---   Northern Fronts   ---   Emitter 3Ditor
INFORMATIVE THREAD TITLES PLEASE. "PLEASE HELP" IS NOT ONE..
Chuck Norris can divide by zero.

Unnamed

  • Guest
Re:Rank function - Help needed
« Reply #11 on: 13 Sep 2004, 00:00:17 »
Quote
But, if you take a look at the quoted code, the _unit is initialized outside the first {}...

Yeah, I just commented on the smaller code section you quoted as I had the same problem not so long back. Took me ages to work out why :(

I see you do a check for _unit=="", does _unit become an empty string because of the call to private? Never thought to check if private actually initalises a variable. Or are you just passing in an emptry string by default?

Quote
Well, in sqf however exit does absolutely nothing...
No matter where you put it...

Yep, just tried a quick test. Never mind, cant say I ever used it in a function.

Offline h-

  • OFPEC Site
  • Administrator
  • *****
  • Formerly HateR_Kint
    • OFPEC
Re:Rank function - Help needed
« Reply #12 on: 13 Sep 2004, 18:26:29 »
Quote
I see you do a check for _unit=="", does _unit become an empty string because of the call to private?
No, it's defined as empty string when calling the function for the "mark" routine...
That's just to test whether the "scalar bool...." was the problem...

_unit is "scalar bool..." if it's not given a 'value' when calling the function...

I have to say I've made no progress... :(

I'm beginning to lean towards breaking the function into parts to see if that helps...

DISREGARD AS RETARDED...
UPDATE:
@GB:
Nope, I just can't get that stuff you suggested to work...

If no unit is passed, or it's substituted with some empty string or so, I get an error when ever a unit is passed...
And furthermore, the mark routine won't run...
And the error is the 'Generic error in expression'...

How on earth can this give the 'Generic...' ???
if (__unit == "")  then {call loadFile "fu.sqf"}    else {_rank = call loadFile "fu2.sqf"};
And the _unit is defined outside the {}...

I think this is actually the reason why I used that horrid "task"/nil stuff (it's been so long time since I started this I just can't remember all the details anymore...) so it seems I need to revert back to using it, because at least with it this function worked :( ....
« Last Edit: 17 Sep 2004, 15:59:03 by HateR_Kint »
Project MCAR   ---   Northern Fronts   ---   Emitter 3Ditor
INFORMATIVE THREAD TITLES PLEASE. "PLEASE HELP" IS NOT ONE..
Chuck Norris can divide by zero.

Offline h-

  • OFPEC Site
  • Administrator
  • *****
  • Formerly HateR_Kint
    • OFPEC
Re:Rank function - Help needed
« Reply #13 on: 17 Sep 2004, 15:54:41 »
Still @GB:
Ehm... :-X
I got that suggestion of yours working and feel such a ****ing dum **********er right now... ::)

One shouldn't be coding gazillion things at the same time, makes the brain retarded after a while...
« Last Edit: 17 Sep 2004, 16:01:02 by HateR_Kint »
Project MCAR   ---   Northern Fronts   ---   Emitter 3Ditor
INFORMATIVE THREAD TITLES PLEASE. "PLEASE HELP" IS NOT ONE..
Chuck Norris can divide by zero.

Offline h-

  • OFPEC Site
  • Administrator
  • *****
  • Formerly HateR_Kint
    • OFPEC
Re:Rank function - Help needed
« Reply #14 on: 17 Sep 2004, 18:40:17 »
Ok, the vehicle check of your Unnamed works just fine, thnx! :)

But, now for more troubles... :(
The code works quite good now, men and other vehicles do return their correct ranks.

However, if used with forEach on a vehicle the 'scalar bool array...' is returned ("[array,_x] call getRank" forEach units group vehicleName)...
Or, if trying to get the rank of a certain individual who is in a vehicle (driver, gunner, commander, cargo) the same 'scalar bool array...' is returned...
Now, this is most likely due to the fact that I have removed all the error checks from the code, but this also means that the code won't work in these situations...
When using a sqs loop (the usual _unit = _list select _i stuff...) the code returns the ranks correctly on an array of men, but not if the array contains men from within a vehicle... In that case the ranks are completely wacked... Only the drivers rank is usually at least close to the real rank...

Hopefully somebody has some suggestions, I'm running out of ideas :-\...

Oh, and here's the current code. The usage is the same as before, but now the 'mark' routine is called with [array] call getRank, and the rank then retrieved with [array,unit] call getRank...:
Code: [Select]
private ["_all","_unit","_task","_mkunit","_mkvunit","_mk_ratU","_mkratUx","_rank","_ratU","_ratUx","_ratUm","_i","_iv"];
_all    = _this select 0;
_unit    = _this select 1;

if (count _this == 1)
 then
    {
     _cnt    = count _all;
     _mkratU   = 0;
     _mkratUx  = 0;
     _i        = 0;

     while "_i < _cnt"
       do
        {
         _mkunit = _all select _i;
         if ((vehicle ((crew _mkunit) select 0)) != ((crew _mkunit) select 0))
          then
             {
          _iv       = 0;
              while "_iv < (count (crew _mkunit))"
                do
                 {
          _mkvunit = ((crew _mkunit) select _iv);
          _mkratUx = rating _mkvunit;
              _mkvunit addRating _mkratUx - (_mkratUx * 2);
                  _mkratU = _mkratUx / 10000;
              _mkvunit addRating (_mkratUx + (_mkratU / 2)) + 10;

          _iv = _iv + 1;
         };
             };
         _mkratUx = rating _mkunit;

     _mkunit addRating _mkratUx - (_mkratUx * 2);
         _mkratU = _mkratUx / 10000;
     _mkunit addRating (_mkratUx + (_mkratU / 2)) + 10;

     _i = _i + 1;
       };
  }
  else
     {
      _ratUx = rating _unit;
      if ((vehicle ((crew _unit) select 0)) != ((crew _unit) select 0))
       then
          {
       _ratUx = rating ((crew _unit) select 0);
      };
    if (_ratUx < 0 && _ratUx > -2000)
        then
       {
        _ratUx = abs _ratUx;
       };
      _ratUm = _ratUx - (_ratUx mod 1);
      _ratU = ((_ratUx - _ratUm) * 10000) + random 3;
      _ratU = _ratU * 2;

     if ((vehicle ((crew _unit) select 0)) != ((crew _unit) select 0) && (((crew _unit) select 0) == gunner _unit || ((crew _unit) select 0) == commander _unit))
       then {_ratU = _ratU - 1000};

   if (_ratU >= 7500)
    then {_rank = "COLONEL";};

   if (_ratU >= 5000 && _ratU < 7500)
    then {_rank = "MAJOR";};

   if (_ratU >= 3500 && _ratU < 5000)
    then {_rank = "CAPTAIN";};

   if (_ratU >= 2500 && _ratU < 3500)
    then {_rank = "LIEUTNANT";};

   if (_ratU >= 1500 && _ratU < 2500)
    then {_rank = "SERGEANT";};

   if (_ratU >= 500 && _ratU < 1500)
    then {_rank = "CORPORAL";};

   if ((_ratU >= 0 && _ratU < 500))
    then {_rank = "PRIVATE";};

   if ((rating _unit) <= -2000 && alive _unit)
    then {_rank = "RENEGADE TREASENOUS BASTARD!!!!";};
     };

_rank

The code is also attached (rename..)... And has that more deatiled usage info...
Project MCAR   ---   Northern Fronts   ---   Emitter 3Ditor
INFORMATIVE THREAD TITLES PLEASE. "PLEASE HELP" IS NOT ONE..
Chuck Norris can divide by zero.

Unnamed

  • Guest
Re:Rank function - Help needed
« Reply #15 on: 18 Sep 2004, 14:42:23 »
Are these problems still with manned vehicles placed in the editor?

I'm not sure the crew exist (in the usual OFP sense) when placed this way. To see what I mean, place a manned tank in the editor, call it V1 then call the following code via a radio trigger:

Code: [Select]
(Gunner V1) SwitchCamera "EXTERNAL"
The view you get looks like that of a seagull, hanging around position [0,0,0]. The same applies if you place a soldier in the editor, then get him to board a cargo position. Call the radio trigger again, and you get a view of the outside on the vehicle. If that vehicle has a move waypoint, you watch it drive away with your AI's body in the back seat. It's as though AI become disembodied when they enter certain positions in a vehicle.

I dont know if this is the cause, but it must have some effect?

It certainly explains some odd things I've noticed in CTI games. Under heavy lag, if the position where your AI board a vehicle is bombed, your AI can die even though there are no longer in the vicinity.

Offline h-

  • OFPEC Site
  • Administrator
  • *****
  • Formerly HateR_Kint
    • OFPEC
Re:Rank function - Help needed
« Reply #16 on: 18 Sep 2004, 15:37:40 »
Quote
Are these problems still with manned vehicles placed in the editor?
Yeah...
I tried an empty vehicle in which I moveInCargoed a soldier, and that didn't help either...

Altough, if you use a sqs loop for the group that's in a vehicle you get some results. but the ranks are wrong (usually one step higher than they should)...

But, as of now, the code won't most likely even consider the cargo as it takes the first element from the crew array and uses it...

Found something 'interesting' about the crew.
If used on a tank, it returns the crew in this order [driver,commander,gunner] and if used on car it returns [driver,gunner]...

Quote
'm not sure the crew exist (in the usual OFP sense) when placed this way
Yeah, I've noticed this too...

Quote
If that vehicle has a move waypoint, you watch it drive away with your AI's body in the back seat. It's as though AI become disembodied when they enter certain positions in a vehicle.
;D ;D
I knew it!
We had philosophy, now there's metaphysics too ;D

The OFP game engine is so 'retarded' in a way... Much stuff left half finished...

Quote
I dont know if this is the cause, but it must have some effect?
Most likely it does...
Project MCAR   ---   Northern Fronts   ---   Emitter 3Ditor
INFORMATIVE THREAD TITLES PLEASE. "PLEASE HELP" IS NOT ONE..
Chuck Norris can divide by zero.

Unnamed

  • Guest
Re:Rank function - Help needed
« Reply #17 on: 18 Sep 2004, 16:03:22 »
Quote
We had philosophy, now there's metaphysics too

LOL

At a push, could you pop each guy out with setpos [0,0,0], get his rank then move him back in?

Offline h-

  • OFPEC Site
  • Administrator
  • *****
  • Formerly HateR_Kint
    • OFPEC
Re:Rank function - Help needed
« Reply #18 on: 18 Sep 2004, 17:55:31 »
Quote
At a push, could you pop each guy out with setpos [0,0,0], get his rank then move him back in?
That actually was my initial thought on how to make this, but I just was convinced that there was some more elegant way :P

Well, needs to test that then...
Project MCAR   ---   Northern Fronts   ---   Emitter 3Ditor
INFORMATIVE THREAD TITLES PLEASE. "PLEASE HELP" IS NOT ONE..
Chuck Norris can divide by zero.

Unnamed

  • Guest
Re:Rank function - Help needed
« Reply #19 on: 19 Sep 2004, 16:30:07 »
Yeah not an ideal solution. But your just runing this once at the start of the mission? What about guys you place in the editor, and set as "In Cargo", do they suffer from the same problem?

Offline h-

  • OFPEC Site
  • Administrator
  • *****
  • Formerly HateR_Kint
    • OFPEC
Re:Rank function - Help needed
« Reply #20 on: 19 Sep 2004, 17:32:29 »
The 'mark' stuff runs once in the beginning (or whenever wanted for that matter)...
And yeah, the In Cargo troops suffer the same problem...

The setPos [0,0,0] stuff ain't actually that easy, and would look horrid on the player... :(
You'd need to store the position of the unit (position in the vehicle, driver, commander, gunner or cargo), then setPos him to [0,0,0] and then moveInxxxxx back to the vehicle in the units correct position... :(

But I have another idea, yet it will fail like all the others probably... :-\
The idea is this:

Code: [Select]
_crw = crew _unit;
_i = 0;
_done = false;
       _ind = call {while {!(_done) && _i < (count _crw)}
              do
           {
            if (_unit == (_crw select _i))
             then {_done = true}
               else {_i = _i + 1};
           };
         if (!(_done))
          then {_i = -1};
         _i
            };
That's a modified version of G Barrons 'indexOf', and it's not functional, but I quoted it there to... ..erm... for some reason I already forgot... ;D ::)

What I need to do is to get the index of the unit in crew/cargo of a vehicle...
But, with indexOf I need to compare the vehicle's crew to itself and that's where I hit the wall... ::)
Because as you would expect
Code: [Select]
(_crw select _i == _crw select _i)returns always true ::)

So I would need to loop through the crew array and check if the unit whose rank is wanted is in the crew array, then get the index of that 'place' in the crew array and use that index to pick up the right element from the crew array to be used with the actual rank return process... *takes a breath*  :P

Anyone? ::) :P
« Last Edit: 19 Sep 2004, 17:35:07 by HateR_Kint »
Project MCAR   ---   Northern Fronts   ---   Emitter 3Ditor
INFORMATIVE THREAD TITLES PLEASE. "PLEASE HELP" IS NOT ONE..
Chuck Norris can divide by zero.

Unnamed

  • Guest
Re:Rank function - Help needed
« Reply #21 on: 20 Sep 2004, 04:08:51 »
I'm not sure what the problem is, I ran this function from a trigger, passing ThisList as the parameter:

Code: [Select]
_Result=_This Select 0;

_Rank=[];

{{_Rank=_Rank+[Rating _x]} ForEach (Crew _x)} ForEach _Result;

Hint Format ["Result %1 %2",_Rank];

_DRating=Rating (Driver (_Result Select 0));
_CRating=Rating (Commander (_Result Select 0));
_GRating=Rating (gunner (_Result Select 0));

Player SideChat Format ["Result %1 %2 %3",_DRating,_CRating,_GRating];

Everything looked ok, each soldiers rating corresponded to the values you use in your function. And was correct for there rank. I tried a MG Jeep and an M2A2.

I noticed that if it's just a driver and gunner (MG Jeep), the driver gets the rank set in the editor, and the gunner one less.

But if it has a commander, gunner and driver, the commander gets 2 ranks higher than the rank set in the editor. The gunner gets one rank higher and the driver has the same rank thats set in the editor. The logic changes slightly when you set the rank at either private or colonel, to accomodate for the two extremes.

If you just have a gunner (M2 Machine Gun), he automaticaly gets his rank raised by one. If you set him to Major in the editor, he becomes a Colonel in the game.

A gunner and Commander used in artillery, behave the same as any other vehicle.

With the exception of the MG jeep, it appears straight forward. You can have options in the config for Cargo as Co driver. Perhaps this is what make the MG Jeep different?




Kammak

  • Guest
Re:Rank function - Help needed
« Reply #22 on: 20 Sep 2004, 18:12:26 »
I don't know if this is still an issue, but a real simple way to find out if a unit is a vehicle or not, is this check:

"man" countType [_unit]==1

where _unit is the item being checked.

So, for example,

if ("man" countType[_unit]==1) then [person code here, or goto]
if ("man" countType[_unit]==0) then [vehicle code here, or goto]



Offline h-

  • OFPEC Site
  • Administrator
  • *****
  • Formerly HateR_Kint
    • OFPEC
Re:Rank function - Help needed
« Reply #23 on: 20 Sep 2004, 19:00:47 »
Quote
Everything looked ok, each soldiers rating corresponded to the values you use in your function.
Yes, I know, I run a test mission with sideChat debug that does exactly same, it returns all the stuff I need to see whether the function works ok...
So, rating returns the correct value, BUT my function somehow doesn't work...
It's either the marking routine that doesn't work (altough I've confirmed that it at least runs, and it's much more 'complicated' than your example, and does not work with forEach for some reason...), or the process of getting the unit from inside a vehicle and then getting the below decimal stuff from the rating doesn't work...

The problem here is that when a unit is inside a vehicle it actually is not in the thisList array...
So, the mark routine checks if the selected unit in the array is a vehicle and then 'goes inside' it and marks all the units in it (at least it should...)

Then, when the rank process is called it needs to be checked whether the passed unit is in a vehicle... And this is actually where I have the problem now... First, I need to determine if the units is in a vehicle, and that's easy...
Then I need the crew array of the vehicle the passed unit is in, then the 'position' (index) of the unit (element) in the crew array in order to get the 'actual unit' (well, the pointer...) from the crew array for the process of getting the below decimal value from that units rating...

But, as usual, I may be thinking this way too complicately... ::)
And doing many other things aside of this, I'm starting to have troubles keeping up myself :P

Quote
I noticed that if it's just a driver and gunner (MG Jeep), the driver gets the rank set in the editor, and the gunner one less [.....
Yeah, like I said, the vehicle rank given in the editor goes to the driver and so on... (of course, if there is a driver in that vehicle...)

Quote
If you just have a gunner (M2 Machine Gun), he automaticaly gets his rank raised by one. If you set him to Major in the editor, he becomes a Colonel in the game.
Noticed this too.
And there's a process now in the function to 'correct' this...

I actually fail to see the BIS logic behind this one...
Wth is the gunners rating being raised like that...??

Quote
With the exception of the MG jeep, it appears straight forward. You can have options in the config for Cargo as Co driver. Perhaps this is what make the MG Jeep different?
Never tested anything with cargoIsCodriver, so won't know what effect it has...

@Kammak:
Yeah, I'm aware of that but that's no longer an issue...
I used that method in some version of this function, but is has some downsides, as  the function deals with the crew of a vehicle, not the actual vehicle itself, the typeOf "man" would always return true...
Meaning, the if ("man" countType[_unit]==1) then {person code here, or goto} would always cause the then part to run...
Project MCAR   ---   Northern Fronts   ---   Emitter 3Ditor
INFORMATIVE THREAD TITLES PLEASE. "PLEASE HELP" IS NOT ONE..
Chuck Norris can divide by zero.

Unnamed

  • Guest
Re:Rank function - Help needed
« Reply #24 on: 20 Sep 2004, 20:08:26 »
Quote
I actually fail to see the BIS logic behind this one...
Wth is the gunners rating being raised like that...??

I just assumed it was for simplicity. All vehicles, at the most will have Gunner, Driver and Commander. Its easier to treat a one man M2 in the same way you would an M2A2, rather than having to make an exception for all the different configurations. Although it looks like they had to in the end, with the MG jeep.

Quote
But, as usual, I may be thinking this way too complicately...
And doing many other things aside of this, I'm starting to have troubles keeping up myself

I must admit I find it hard to follow the code. Putting the rating stuff, into seperate functions would be easier to read.

I'm not sure why you need the indexof?

If you have a three functions MyGetRating,MyCalcRank and MySetRating. Then work sequentialy through the crew array, cant you just get the rating, calculate the rank, then set the new rating all within a ForEach loop.

If you call those three functions from another function, MySetRank. You could have:

MySetRank.sqf:

Code: [Select]
private ["_rank","_unit","_rating"];
_Unit=_This Select 0;

_Rank=0;
_Rating=0;

_Rating=[_Unit] Call MyGetRating;
_Rank=[_Rating] Call MycalcRank;
[_Rank,_Unit] Call MySetRating;

And another function, MyIsVehicle. Ok, so I like functions :)

MyIsVehicle.sqf:

Code: [Select]
private ["_Unit"];
_Unit=_This Select 0;
(((Crew _Unit) Select 0)!=Vehicle ((Crew _Unit) Select 0))

Then the function the user calls should just be:

Code: [Select]
private ["_triggerlist"];
_TriggerList=_This Select 0;

{If ([_x] Call MyIsVehicle) Then {{[_x] Call MySetRank} ForEach (Crew _x)} Else {[_x] Call MySetRank}} Foreach _TriggerList;

I did not get as far as trying to set a crew members rating, so If I'm missing one of those little OFP foibles. My apology. But at least it should be easier to debug?
« Last Edit: 20 Sep 2004, 20:09:28 by Unnamed »

Offline h-

  • OFPEC Site
  • Administrator
  • *****
  • Formerly HateR_Kint
    • OFPEC
Re:Rank function - Help needed
« Reply #25 on: 20 Sep 2004, 20:36:58 »
Quote
I must admit I find it hard to follow the code
;D
And you wrote the FO stuff from which I don't understand dick... ::)

Quote
Putting the rating stuff, into seperate functions would be easier to read
Yeah, but I want this to be a 'real' function, not bundle of them...

Quote
If you have a three functions MyGetRating,MyCalcRank and MySetRating. Then work sequentialy through the crew array, cant you just get the rating, calculate the rank, then set the new rating all within a ForEach loop
Why use more files as you can have all these functions within one??
And actually this wouldn't change anything...
The same problems would still be there (I think...)...

Quote
I'm not sure why you need the indexof?
Because you can't pick anything from an array by using it's 'name', like _array select _unit... _unit being the vehicle/man/whatever in question...
Or can you??

But you may be right... I'm actually started questioning the necessity of indexOf myself... dunno...
Project MCAR   ---   Northern Fronts   ---   Emitter 3Ditor
INFORMATIVE THREAD TITLES PLEASE. "PLEASE HELP" IS NOT ONE..
Chuck Norris can divide by zero.

Unnamed

  • Guest
Re:Rank function - Help needed
« Reply #26 on: 20 Sep 2004, 21:03:07 »
Quote
Why use more files as you can have all these functions within one??

It's just easier to debug, does not help when the forum messes up the code formatting either. Difficult to follow all those if thens.

You can always bundle them back up once your happy they work. And they dont have to be files, each function could be a string.

Quote
Because you can't pick anything from an array by using it's 'name', like _array select _unit... _unit being the vehicle/man/whatever in question...

You dont have to when you use the foreach command. You just start at the begining and work your way though. But again, I might have missed something regarding how you determine rank. I assume it's based puerly on each units rating and not there position?

Offline h-

  • OFPEC Site
  • Administrator
  • *****
  • Formerly HateR_Kint
    • OFPEC
Re:Rank function - Help needed
« Reply #27 on: 22 Sep 2004, 20:47:32 »
Ended up using that forEach...
But it only works in the rank routine, the mark stuff it can't handle...
But that's no biggy, the stuff works...

To a certain extent... ::)
Now as the function works on vehicles it stopped working on troops :P
Huge troubles over a function no-one will ever use ... ::) :P

Ended up having helluva lot of different 'if-this-is-so-then-this-must-be * 2-but-if-like-this-then-not' because OFP is a mental case of ratings when it comes to vehicles...
Project MCAR   ---   Northern Fronts   ---   Emitter 3Ditor
INFORMATIVE THREAD TITLES PLEASE. "PLEASE HELP" IS NOT ONE..
Chuck Norris can divide by zero.