Home   Help Search Login Register  

Author Topic: Scoring System for Single Player  (Read 1809 times)

0 Members and 1 Guest are viewing this topic.

Offline p0gie

  • Members
  • *
Scoring System for Single Player
« on: 30 Dec 2007, 19:58:49 »
I spent hours yesterday trying to find a solution to this or a pointer in the right direction but didn't come up with anything.

I am building a single player mission inspired by the awesome evolution.  I need a points system that adds a score depending on what type of unit you or your squad just killed.  Enemy forces in this mission would be generated dynamically.  I've had a look through some other scripts and have seen it done through the init.sqf in the case of the Zombie Quarantine mission..  but here it is just one enemy.  I've spent ages looking through the EVO single player scripts but I can't find anywhere this is referred to.

Does something need to be initialised for each enemy that is created or can it be handled globally for any kills on the whole map?

Any pointers in the right direction would be hugely appreciated.  Thanks in advance.

Offline Mandoble

  • Former Staff
  • ****
    • Grunt ONE and MandoMissile suite
Re: Scoring System for Single Player
« Reply #1 on: 30 Dec 2007, 20:16:59 »
addEventHandler command

Event handlers type

When you create an enemy unit, add a "Killed" event handler to it, when the unit dies, the script is executed and you get the killed unit into _this select 0 and the killer into _this select 1

Code: [Select]
_eh_idx = _new_unit addEventHandler ["Killed", {hint format["%1 was killed by %2, I need to increase the score of %2", _this select 0,_this select 1]}];

In the script, just check the typeOf (_this select 0) and based on that increase the custom score of (_this select 1)

EDIT:
And to add a particular score to any unit you may use setVariable command and to retrieve the value use getVariable command.


For example:
Code: [Select]
_eh_idx = _new_unit addEventHandler ["Killed", {res = _this execVM "Im_down.sqf"}]


Code: [Select]
// Im_down.sqf
_killed = _this select 0;
_killer = _this select 1;
_var = _killer getVariable "my_score";

// make _score_to_add dependant on typeOf _killed
_score_to_add = 100;

if (isNil "_var") then
{
   _killer setVariable ["my_score", _score_to_add];
}
else
{
   _killer setVariable ["my_score", (_killer getVariable "my_score") + _score_to_add];
};
« Last Edit: 30 Dec 2007, 20:29:25 by Mandoble »

Offline p0gie

  • Members
  • *
Re: Scoring System for Single Player
« Reply #2 on: 30 Dec 2007, 23:18:33 »
Thanks a lot.  That should get me started.  I'll play around with this today and see how I get on.

Offline Wolfrug

  • Addons Depot
  • Former Staff
  • ****
  • Official OFPEC Old Timer
Re: Scoring System for Single Player
« Reply #3 on: 31 Dec 2007, 02:06:51 »
You -caaan- also use the rating command (I use it in my DSAI scripts to spot kills). It only increases naturally via kills. The caveat is, of course, that if you're using it for anything else (addRating that is), it'll activate your script. ALSO, it's preciseness is a bit so-and-so, since you'd basically have to watch very closely for any changes all the time (i.e. waitUntil commands). Of course, the Rating command has the bonus of automatically scaling itself according to the rank and type of unit killed (more points for armor, higher ranking officers, more important units etc - it's how the ArmA AI keeps track of who to target first).

So from that perspective, eventhandlers will be considerably more resource friendly :) However if you're -only- watching for kills from one unit (=the player) then I don't see how a single simple waitUntil could be -that- bad. But when it comes to whole squads of units and such, it might not be so good. Example (simple) code:

Code: [Select]
_unit = _this select 0;

while {alive _unit} do
{
_rating = rating _unit;
waitUntil ((rating _unit) > _rating};
// Add code here on what to do. I'll use Mandoble's example here. Note that "score to add" could as well be something like: ((rating _unit) - _rating) to get the difference in ratings (so that you get more score for more valuable targets etc).

_score_to_add = 100;

if (isNil "_var") then
{
   _unit setVariable ["my_score", _score_to_add];
}
else
{
   _unit setVariable ["my_score", (_unit getVariable "my_score") + _score_to_add];
};
sleep 0.02;
};

Untested, but should work :)

Good luck!

Wolfrug out.
"When 900 years YOU reach, look as good you will not!"

Offline p0gie

  • Members
  • *
Re: Scoring System for Single Player
« Reply #4 on: 31 Dec 2007, 07:08:09 »
Ok..  struggling a bit..  been a while since I did anything involving any programming.

Just as a simple test I have this in the init field of an OPFOR soldier:

this addEventHandler ["Killed", {res = _this execVM "infkilled.sqf"}]

I at least know this works because I just put a dummy display message in here initially to make sure the script was called.  At the moment I am just trying to get it working without worrying about dynamic units being initialised properly.

Now for the script itself:

// Infantry Killed Points Allocation

_killed = _dead;
_killer = _player;
_var = _killer getVariable "SPON_playerCashBalance";

// make _score_to_add dependant on typeOf _killed

if ((typeOf _dead) == OfficerE)
{
   _score_to_add = 100;
}
else
{
   _score_to_add = 50;
};


_killer setVariable ["SPON_playerCashBalance", (_killer getVariable "SPON_playerCashBalance") + _score_to_add];


Something is wrong somewhere.  I am assuming the bottom of the script has an error check built in where it says if (isNil "_var"), or not..  I'm not sure if that needed to be left in or not.



Offline Mandoble

  • Former Staff
  • ****
    • Grunt ONE and MandoMissile suite
Re: Scoring System for Single Player
« Reply #5 on: 31 Dec 2007, 12:03:49 »
if (isNil "_var") ensures the corresponding vehicle var already exists, because if not this (_killer getVariable "SPON_playerCashBalance") + _score_to_add will never work.

You are missing a "then" after if ((typeOf _dead) == OfficerE)

Offline Spooner

  • Members
  • *
  • Mostly useless
    • Community Base Addons
Re: Scoring System for Single Player
« Reply #6 on: 31 Dec 2007, 14:04:35 »
At the top of the event handler code, you need to read in your variables from the _this array. _dead and _player aren't pre-set. You also need to ignore any deaths not caused by the player.
Code: [Select]
_killed = _this select 0;
_killer = _this select 1;

if (_killer != player) exitWith {};

_var = _killer getVariable "SPON_playerCashBalance";

You have already worked out _var, so you can use that at the end rather than re-calculating it. Incidentally, since SPON Money always sets the player's "SPON_playerCashBalance" variable to a non-nil value and you have already exited the script if the killer is not the player (see the previous example), you can actually safely assume that _var is non-nil (though there is no harm in double-checking if you are paranoid).
Code: [Select]
_killer setVariable ["SPON_playerCashBalance", _var + _score_to_add];

Object classes are strings, so need to be put in quotes. You also need to remember that if requires then:
Code: [Select]
if ((typeOf _dead) == "OfficerE") then
{
[Arma 2] CBA: Community Base Addons
[Arma 1] SPON Core (including links to my other scripts)

Offline p0gie

  • Members
  • *
Re: Scoring System for Single Player
« Reply #7 on: 01 Jan 2008, 05:22:42 »
Thanks for the help guys...  I now have the script running error free but it doesn't seem to be doing what I want it to do.  I put 2 units in the editor, 1 officer and 1 rifleman both running the script.  When I kill either of them my cash balance remains at its starting level and doesn't change. 

Code is now:

// infkilled.sqf

_killed = _this select 0;
_killer = _this select 1;

if (_killer != player) exitWith {};

_var = _killer getVariable "SPON_playerCashBalance";

// make _score_to_add dependant on typeOf _killed

if ((typeOf _dead) == OfficerE) then
{
   _score_to_add = 100;
}
else
{
   _score_to_add = 50;
};

_killer setVariable ["SPON_playerCashBalance", _var + _score_to_add];


This is probably more a question for Spooner as it is his shop system I am using.  Do I need to use a SPON_AddEventHandler also?  I notice in the init.sqs of the zombie quarantine mission it seems to be used.  e.g.

["zombieKilledEvent",
    {
        if (player == zombieKiller) then
        {
            SPON_playerCashBalance = SPON_playerCashBalance + 50;
player groupchat format ["50 zombie kill bonus!%1",SPON_playerCashBalance]
        };
    }
] call SPON_addEventHandler;

Offline Spooner

  • Members
  • *
  • Mostly useless
    • Community Base Addons
Re: Scoring System for Single Player
« Reply #8 on: 01 Jan 2008, 07:12:25 »
- Object classes, as used with typeOf or isKindOf, are strings (e.g. "OfficerE"), not variables (e.g. OfficerE), so need to be put inside quotes.
- You should use typeOf _killed (not typeOf the undefined _dead variable).
- You need to define _score_to_add outside the if/then/else or it is local to the if block and won't be accessible outside that block.
Code: [Select]
private "_score_to_add";
if ((typeOf _killed) == "OfficerE") then
{
   _score_to_add = 100;
}
else
{
   _score_to_add = 50;
};

The MP zombie Quarantine mission requires a SPON event (or, as I have posted in the release thread for that mission, a publicVariable event is better now that ArmA 1.09 has been released) in order to tell the correct player to add bounty money when a zombie dies (the killed event occurs on the MP server, where the zombies are local, but the cash needs to be added on the player's machine). Since you are making an SP mission, there is no need for any communication between machines and you can get away with a simple setVariable on the local player object (the "server" machine where the zombies are is the same machine as the one the player is playing on).
« Last Edit: 01 Jan 2008, 07:13:59 by Spooner »
[Arma 2] CBA: Community Base Addons
[Arma 1] SPON Core (including links to my other scripts)

Offline p0gie

  • Members
  • *
Re: Scoring System for Single Player
« Reply #9 on: 02 Jan 2008, 06:40:31 »
Wooo..  it works.. after much  :banghead:

The working script is:

// infkilled.sqf

_killed = _this select 0;
_killer = _this select 1;

if (_killer != player) exitWith {};

// make _score_to_add dependant on typeOf _killed

private "_score_to_add";

if ((typeOf _killed) == "OfficerE") then
{
   _score_to_add = 100;
}
else
{
   _score_to_add = 50;
};

SPON_playerCashBalance = SPON_playerCashBalance + _score_to_add;


I think for the sake of SP the SPON cash balance acts as somewhat of a global variable and does not need to be a variable attached to the player..  So now..  go beyond the basics and some tweaking and I can move on.  Thank you for your help.

Offline Spooner

  • Members
  • *
  • Mostly useless
    • Community Base Addons
Re: Scoring System for Single Player
« Reply #10 on: 02 Jan 2008, 12:59:00 »
Indeed, SPON_playerCashBalance could be a global variable rather than an object variable in SP or MP and have the same effect. In fact, it used to be implemented this way, but then it was incompatible with SP teamswitch and people complained so I changed it to be a variable on an individual, which works in all cases. SPON_playerBankBalance has always been a plain global variable. Although
Code: [Select]
SPON_playerBankBalance = SPON_playerBankBalance + _score_to_add;

would work,
Code: [Select]
SPON_playerCashBalance = SPON_playerCashBalance + _score_to_add;

wouldn't because there is no such variable (well, at least, the global variable SPON_playerCashBalance is not used by SPON Money, which uses the "SPON_playerCashBalance" variable on the player object).

Incidentally, you can write out your scripts in the forum inside a code tag to make it clearer (it is the little button marked with a "#" above where you type in your post).
[Arma 2] CBA: Community Base Addons
[Arma 1] SPON Core (including links to my other scripts)