Hi everyone!

I'm hoping to get some advice, a game I have been dying to mod is written in Pascal, most of the files are accessible for easy modding so that is a great start.


It's a strategy game, its the usual resource gathering/build an army setup, what makes it realistic is that each unit consumes food, if you run out of food you have a famine and the units start to die, so this is a really cool feature of the game. To add to the realism what I want to add to the game is also have supply wagons. What would happen would be that units health slowly decreases unless you have a supply wagon in a certain radius of your units and your units health will be increased to full/not decrease.

So what I need to do is code so that units health is always decreasing (at a certain rate) unless their is a supply wagon nearby, the supply wagon replenishes health. There is already a Priest unit in the game that heals units that are attacked in battle, so that side of things will be easy because I can just use the code from the Priest unit to replenish health, so really all I need to do is get units health to decrease, the rest would be easy. I have spoken to the devs and they said its something that can be done, I have this famine code which the game uses when food runs out and units start dying, I would love to understand the code so I can go from there:

The dev explained this to me:

look at current famine code:
scripts\units\unit.inc\nothing.inc

You should change it to be effective all the time (except supply unit`s nearby) and change it to draining unit hp, instead of killing it.

You may use famine code, and replace
_unit_SetTagStates(myHnd, gc_statetag_essential_death);
with code for decreasing current health (please, check TObj class declaration in dmscript.global, located in scripts\).
Also you'd have to set some kind of timer, to let the health decline slowly.
As for supply unit - you may add a check of it's availability (no need to use pope's code, just make a unique sid for this unit and check it, it'd be a slow solution though, i'd recommend putting a large timer to it), and in case it's near just inverse the health decreasement variable.
A viable alternative to sid would be adding another property to objprop class (classes.script in scripts\lib) and setting it false for all the units (initbase function in unit.script) except supply unit.
The entire famine code looks like this:


Code:
[*] = ;         if gProfile.bFamine and (gPlayer[plInd].bfamine) and (bplayable) then
        [*] = ;         begin
        [*] = ;            if (gInterface.gamemode=gc_gamemode_game) or (gInterface.gamemode=gc_gamemode_spectator) then
        [*] = ;            begin
        [*] = ;               if (not TObjProp(pobjprop).bbuilding) and (not TObjProp(pobjprop).bnohungry) then
        [*] = ;               begin
        [*] = ;                  if (arg_obj.insideofuid<>0) and (gPlayer[plInd].difficulty>0) then // won't be here, cause unit insideofuid is unplayable
        [*] = ;                  begin
        [*] = ;                     // случай, если юнит сидит в шахте
        [*] = ;                     {var absorberHnd : Integer = GetGameObjectHandleByUniqueId(arg_obj.insideofuid);
        [*] = ;                     if (absorberHnd<>0) then
        [*] = ;                     begin
        [*] = ;                        var pobj2 : Pointer = _unit_GetTObj(absorberHnd);
        [*] = ;                        if (pobj2<>nil) then
        [*] = ;                        begin
        [*] = ;                           if (gObjProp[TObj(pobj2).cid][TObj(pobj2).id].usage=gc_obj_usage_mine) then
        [*] = ;                           begin
        [*] = ;                              var pObjInside : Pointer = _misc_GetObjectArgData(absorberHnd, gc_argunit_inside);
        [*] = ;                              var insidecount2 : Integer;
        [*] = ;                              if pObjInside <> nil then
        [*] = ;                              insidecount2 := TIntegerList(pObjInside).GetCount;
        [*] = ;
        [*] = ;                              if (insidecount2>0) and (_misc_RandomInt<(250/insidecount2)) then
        [*] = ;                              begin
        [*] = ;                                 _unit_SetTagStates(myHnd, gc_statetag_essential_death);
        [*] = ;                                 arg_obj.insideofuid := 0;
        [*] = ;                              end;
        [*] = ;                           end;
        [*] = ;                        end;
        [*] = ;                     end;}
        [*] = ;                  end
        [*] = ;                  else
        [*] = ;                  if (((gPlayer[plInd].difficulty>1) or (gbool_lan_isonlinecached)) and (_misc_RandomInt<50)) or ((gPlayer[plInd].difficulty=0) and (_misc_RandomInt<5)) or ((gPlayer[plInd].difficulty=1) and (_misc_RandomInt<12)) then
        [*] = ;                  _unit_SetTagStates(myHnd, gc_statetag_essential_death);
        [*] = ;               end;
        [*] = ;            end;
        [*] = ;         end;