From ecdb1d3e62ab2322b82c1a4eae95f7d6f7c26c8f Mon Sep 17 00:00:00 2001
From: mr-russ <>
Date: Sun, 21 Sep 2003 11:13:42 +0000
Subject: [PATCH] Made regeneration configurable for all units Small fix to
 _RepairCosts.  Has correct name for its use. Small fix to Use backgrounds
 from first race as well.

---
 doc/ChangeLog.html            |  1 +
 doc/scripts/research.html     |  2 ++
 doc/scripts/unittype.html     |  4 ++++
 src/action/action_repair.cpp  |  4 ++--
 src/include/unittype.h        |  9 +++++++--
 src/include/upgrade_structs.h |  2 ++
 src/stratagus/stratagus.cpp   |  3 +--
 src/unit/script_unittype.cpp  | 10 +++++++++-
 src/unit/unit.cpp             | 17 ++++++-----------
 src/unit/unittype.cpp         |  4 +++-
 src/unit/upgrade.cpp          | 16 +++++++++++++---
 11 files changed, 50 insertions(+), 22 deletions(-)

diff --git a/doc/ChangeLog.html b/doc/ChangeLog.html
index 4792f911d..b7086207f 100644
--- a/doc/ChangeLog.html
+++ b/doc/ChangeLog.html
@@ -36,6 +36,7 @@
 <li>Future 1.19 Release<p>
     <ul>
     <li>++
+    <li>Made regeneration available to all units (from Russell Smith).
     <li>Made damage display missile configurable in ccl (from Russell Smith).
     <li>Made explode-when-killed define a missile (from Russell Smith).
     <li>Fixed bug: did not save improve-production (from Russell Smith).
diff --git a/doc/scripts/research.html b/doc/scripts/research.html
index ae657b065..cc2686fc6 100644
--- a/doc/scripts/research.html
+++ b/doc/scripts/research.html
@@ -219,6 +219,8 @@ all old units and any new unit of a player.
   <dd>Change the hit points of all units of the unit-types given with
   '(apply-to ...).
   </dd>
+  <dt>'(regeneration-rate N)</dt>
+  <dd>amount of HP a unit gains per seconds</dt>
   <dt>'(time-cost N)</dt>
   <dd>Change the time costs (research time or build time) of all unit-types
   or upgrade-ids given with '(apply-to ...).
diff --git a/doc/scripts/unittype.html b/doc/scripts/unittype.html
index e65b1ee05..57c2f4a6d 100644
--- a/doc/scripts/unittype.html
+++ b/doc/scripts/unittype.html
@@ -151,6 +151,8 @@ Possible tags:
 <dt>hp</dt>
 <dd>.
 </dd>
+<dt>regeneration-rate</dt>
+<dd>amount of HP a unit gains per seconds</dt>
 <dt>costs</dt>
 <dd>.
 </dd>
@@ -368,6 +370,8 @@ be very fair.<p></dd>
 <dd></dd>
 <dt>points</dt>
 <dd></dd>
+<dt>regeneration-rate</dt>
+<dd>amount of HP a unit gains per seconds</dt>
 <dt>missile</dt>
 <dd></dd>
 <dt>corpse</dt>
diff --git a/src/action/action_repair.cpp b/src/action/action_repair.cpp
index 7ef6ce483..3e614b8bb 100644
--- a/src/action/action_repair.cpp
+++ b/src/action/action_repair.cpp
@@ -106,7 +106,7 @@ local void RepairUnit(Unit* unit, Unit* goal)
 	//  Check if enough resources are available
 	//
 	for (i = 1; i < MaxCosts; ++i) {
-	    if (player->Resources[i] < goal->Type->_RepairCosts[i]) {
+	    if (player->Resources[i] < goal->Type->RepairCosts[i]) {
 		snprintf(buf,100,"We need more %s for repair!",DefaultResourceNames[i]);
 		NotifyPlayer(player, NotifyYellow, unit->X, unit->Y,buf);
 		if( player->Ai ) {
@@ -129,7 +129,7 @@ local void RepairUnit(Unit* unit, Unit* goal)
 	//
 	//  Subtract the resources
 	//
-	PlayerSubCosts(player, goal->Type->_RepairCosts);
+	PlayerSubCosts(player, goal->Type->RepairCosts);
     }
 
     //
diff --git a/src/include/unittype.h b/src/include/unittype.h
index d1271ff49..27343ad88 100644
--- a/src/include/unittype.h
+++ b/src/include/unittype.h
@@ -172,7 +172,7 @@
 **		The HP given to a unit each cycle it's repaired.
 **		If zero, unit cannot be repaired
 **
-**	UnitType::_RepairCosts[::MaxCosts]
+**	UnitType::RepairCosts[::MaxCosts]
 **
 **		Costs per repair cycle to fix a unit.
 **
@@ -229,6 +229,10 @@
 **
 **		Piercing damage dealt
 **
+**	UnitType::_RegenerationRate
+**
+**		Regeneration rate in HP per second
+**
 **	UnitType::WeaponsUpgradable
 **
 **		Weapons could be upgraded
@@ -709,7 +713,7 @@ struct _unit_type_ {
 
     int		_Costs[MaxCosts];	/// How many resources needed
     int		RepairHP;		/// Amount of HP per repair
-    int		_RepairCosts[MaxCosts]; /// How much it costs to repair
+    int		RepairCosts[MaxCosts]; /// How much it costs to repair
 
     int		TileWidth;		/// Tile size on map width
     int		TileHeight;		/// Tile size on map height
@@ -724,6 +728,7 @@ struct _unit_type_ {
     int		Priority;		/// Priority value / AI Treatment
     int		_BasicDamage;		/// Basic damage dealt
     int		_PiercingDamage;	/// Piercing damage dealt
+    int		_RegenerationRate;	/// HP regeneration HP per sec
     int		WeaponsUpgradable;	/// Weapons could be upgraded
     int		ArmorUpgradable;	/// Armor could be upgraded
     // FIXME: original only visual effect, we do more with this!
diff --git a/src/include/upgrade_structs.h b/src/include/upgrade_structs.h
index 3b9a4dcd5..0b22d6118 100644
--- a/src/include/upgrade_structs.h
+++ b/src/include/upgrade_structs.h
@@ -125,6 +125,7 @@ typedef struct _unit_stats_ {
     int		PiercingDamage;		/// weapon piercing damage
     int		Speed;			/// movement speed
     int		HitPoints;		/// hit points
+    int		RegenerationRate;	/// HP regeration rate in HP
     int		Costs[MaxCosts];	/// current costs of the unit
     int		Level;			/// unit level (upgrades)
 } UnitStats;
@@ -157,6 +158,7 @@ typedef struct _modifiers_ {
     int	Armor;				/// armor modifier
     int	Speed;				/// speed modifier (FIXME: not working)
     int	HitPoints;			/// hit points modifier
+    int RegenerationRate;		/// HP regeneration rate modifier
 
     int	Costs[MaxCosts];		/// costs modifier
 } Modifiers;
diff --git a/src/stratagus/stratagus.cpp b/src/stratagus/stratagus.cpp
index 68b6cad43..899d093b7 100644
--- a/src/stratagus/stratagus.cpp
+++ b/src/stratagus/stratagus.cpp
@@ -1040,8 +1040,7 @@ global void PreMenuSetup(void)
     LoadCursors(PlayerRaces.Name[0]);
     InitSettings();
 
-    InitUserInterface(PlayerRaces.Count>1 ? PlayerRaces.Name[1] :
-	PlayerRaces.Name[0]);
+    InitUserInterface(PlayerRaces.Name[0]);
     LoadUserInterface();
 }
 
diff --git a/src/unit/script_unittype.cpp b/src/unit/script_unittype.cpp
index 470d1bf97..34ffa4189 100644
--- a/src/unit/script_unittype.cpp
+++ b/src/unit/script_unittype.cpp
@@ -117,6 +117,8 @@ local SCM CclDefineUnitType(SCM list)
 	DebugLevel3Fn("Defining unit-type `%s'\n" _C_ str);
 	type=NewUnitTypeSlot(str);
 	redefine = 0;
+	//Set some default values
+	type->_RegenerationRate=0;
     }
 
     type->NumDirections=8;
@@ -252,6 +254,9 @@ local SCM CclDefineUnitType(SCM list)
 	} else if( gh_eq_p(value,gh_symbol2scm("hit-points")) ) {
 	    type->_HitPoints=gh_scm2int(gh_car(list));
 	    list=gh_cdr(list);
+	} else if( gh_eq_p(value,gh_symbol2scm("regeneration-rate")) ) {
+	    type->_RegenerationRate=gh_scm2int(gh_car(list));
+	    list=gh_cdr(list);
 	} else if( gh_eq_p(value,gh_symbol2scm("max-mana")) ) {
 	    type->_MaxMana=gh_scm2int(gh_car(list));
 	    if( type->_MaxMana>MaxMana ) {
@@ -395,7 +400,7 @@ local SCM CclDefineUnitType(SCM list)
 	    while( !gh_null_p(sublist) ) {
 		value=gh_car(sublist);
 		sublist=gh_cdr(sublist);
-		type->_RepairCosts[CclGetResourceByName(value)]=gh_scm2int(gh_car(sublist));
+		type->RepairCosts[CclGetResourceByName(value)]=gh_scm2int(gh_car(sublist));
 		sublist=gh_cdr(sublist);
 	    }
 	} else if( gh_eq_p(value,gh_symbol2scm("can-target-land")) ) {
@@ -661,6 +666,9 @@ local SCM CclDefineUnitStats(SCM list)
 	} else if( gh_eq_p(value,gh_symbol2scm("hit-points")) ) {
 	    stats->HitPoints=gh_scm2int(gh_car(list));
 	    list=gh_cdr(list);
+	} else if( gh_eq_p(value,gh_symbol2scm("regeneration-rate")) ) {
+	    stats->RegenerationRate=gh_scm2int(gh_car(list));
+	    list=gh_cdr(list);
 	} else if( gh_eq_p(value,gh_symbol2scm("costs")) ) {
 	    sublist=gh_car(list);
 	    list=gh_cdr(list);
diff --git a/src/unit/unit.cpp b/src/unit/unit.cpp
index 96c19b53b..a57bcca7f 100644
--- a/src/unit/unit.cpp
+++ b/src/unit/unit.cpp
@@ -1596,21 +1596,15 @@ global void UnitIncrementMana(void)
  **
  **	@note:	We could build a table of all regenerating units reducing cpu
  **		use.
- **		Any idea how to handle this more general? It whould be nice
- **		to have more units that could regenerate.
  */
 global void UnitIncrementHealth(void)
 {
     Unit** table;
     Unit* unit;
-    int regeneration;
-
-    // FIXME: move to init code! (Can't be done here, load/save!)
-    regeneration=UpgradeIdByIdent("upgrade-berserker-regeneration");
 
     for( table=Units; table<Units+NumUnits; table++ ) {
 	unit=*table;
-	if (HitPointRegeneration &&  unit->HP<unit->Stats->HitPoints) {
+	if (HitPointRegeneration && unit->HP<unit->Stats->HitPoints) {
 	    ++unit->HP;
 
 	    if( 0 ) {		// some frames delayed done my color cycling
@@ -1620,10 +1614,11 @@ global void UnitIncrementHealth(void)
 		MustRedraw|=RedrawInfoPanel;
 	    }
 	}
-	if( unit->Type==UnitTypeBerserker
-		&& unit->HP<unit->Stats->HitPoints
-		&& UpgradeIdAllowed(unit->Player,regeneration)=='R' ) {
-	    ++unit->HP;			// FIXME: how fast do we regenerate
+	if( unit->Stats->RegenerationRate && unit->HP<unit->Stats->HitPoints ) {
+	    unit->HP+=unit->Stats->RegenerationRate;
+	    if( unit->HP > unit->Stats->HitPoints ) {
+		unit->HP = unit->Stats->HitPoints;
+	    }
 
 	    // some frames delayed done my color cycling
 	    if( 0 ) {
diff --git a/src/unit/unittype.cpp b/src/unit/unittype.cpp
index c08f783e1..9ebbad95e 100644
--- a/src/unit/unittype.cpp
+++ b/src/unit/unittype.cpp
@@ -720,7 +720,7 @@ local void SaveUnitType(CLFile* file,const UnitType* type,int all)
 		} else {
 		    CLprintf(file," ");
 		}
-		CLprintf(file,"%s %d",DefaultResourceNames[i],type->_RepairCosts[i]);
+		CLprintf(file,"%s %d",DefaultResourceNames[i],type->RepairCosts[i]);
 	    }
 	}
     }
@@ -737,6 +737,7 @@ local void SaveUnitType(CLFile* file,const UnitType* type,int all)
     }
     CLprintf(file,"  'speed %d\n",type->_Speed);
     CLprintf(file,"  'hit-points %d\n",type->_HitPoints);
+    CLprintf(file,"  'regeneration-rate %d\n",type->_RegenerationRate);
     if( all || type->_MaxMana ) {
 	CLprintf(file,"  'max-mana %d\n",type->_MaxMana);
     }
@@ -1085,6 +1086,7 @@ local void SaveUnitStats(const UnitStats* stats,const char* ident,int plynr,
     CLprintf(file,"'basic-damage %d ",stats->BasicDamage);
     CLprintf(file,"'piercing-damage %d ",stats->PiercingDamage);
     CLprintf(file,"'hit-points %d\n  ",stats->HitPoints);
+    CLprintf(file,"  'regeneration-rate %d\n",stats->RegenerationRate);
     CLprintf(file,"'costs '(");
     for( j=0; j<MaxCosts; ++j ) {
 	if( j ) {
diff --git a/src/unit/upgrade.cpp b/src/unit/upgrade.cpp
index 0bc18172c..632ec706d 100644
--- a/src/unit/upgrade.cpp
+++ b/src/unit/upgrade.cpp
@@ -51,7 +51,7 @@
 
 #include "etlib/hash.h"
 
-local int AddUpgradeModifierBase(int,int,int,int,int,int,int,int,int*,
+local int AddUpgradeModifierBase(int,int,int,int,int,int,int,int,int,int*,
 	const char*,const char*,const char*,UnitType*);
 local int AddUpgradeModifier(int,int,int,int,int,int,int,int,int*,
 	const char*,const char*,const char*);
@@ -618,6 +618,10 @@ global void SaveUpgrades(CLFile* file)
 	    CLprintf(file,"\n  '(hit-points %d)"
 		    ,UpgradeModifiers[i]->Modifier.HitPoints );
 	}
+	if( UpgradeModifiers[i]->Modifier.RegenerationRate ) {
+	    CLprintf(file,"\n  '(regeneration-rate %d)"
+		    ,UpgradeModifiers[i]->Modifier.RegenerationRate );
+	}
 
 	for( j=0; j<MaxCosts; ++j ) {
 	    if( UpgradeModifiers[i]->Modifier.Costs[j] ) {
@@ -721,6 +725,7 @@ local SCM CclDefineModifier(SCM list)
     int piercing_damage;
     int armor;
     int speed;
+    int regeneration_rate;
     int hit_points;
     int costs[MaxCosts];
     char units[UnitTypeMax];
@@ -735,6 +740,7 @@ local SCM CclDefineModifier(SCM list)
     armor=0;
     speed=0;
     hit_points=0;
+    regeneration_rate=0;
     memset(costs,0,sizeof(costs));
     memset(units,'?',sizeof(units));
     memset(upgrades,'?',sizeof(upgrades));
@@ -770,6 +776,8 @@ local SCM CclDefineModifier(SCM list)
 	    speed=gh_scm2int(gh_cadr(value));
 	} else if( gh_eq_p(temp,gh_symbol2scm("hit-points")) ) {
 	    hit_points=gh_scm2int(gh_cadr(value));
+	} else if( gh_eq_p(temp,gh_symbol2scm("regeneration-rate")) ) {
+	    regeneration_rate=gh_scm2int(gh_cadr(value));
 	} else if( gh_eq_p(temp,gh_symbol2scm("time-cost")) ) {
 	    costs[0]=gh_scm2int(gh_cadr(value));
 	} else if( gh_eq_p(temp,gh_symbol2scm("gold-cost")) ) {
@@ -815,7 +823,7 @@ local SCM CclDefineModifier(SCM list)
     }
 
     AddUpgradeModifierBase(uid,attack_range,sight_range,
-	    basic_damage,piercing_damage,armor,speed,hit_points,costs,
+	    basic_damage,piercing_damage,armor,speed,hit_points,regeneration_rate,costs,
 	    units,upgrades,apply_to,convert_to);
 
     return SCM_UNSPECIFIED;
@@ -1027,7 +1035,7 @@ global void UpgradesCclRegister(void)
 */
 local int AddUpgradeModifierBase(int uid,int attack_range,int sight_range,
     int basic_damage,int piercing_damage,int armor,int speed,
-    int hit_points,int* costs,const char* af_units,
+    int hit_points,int regeneration_rate, int* costs,const char* af_units,
     const char* af_upgrades,const char* apply_to,UnitType* convert_to)
 {
     int i;
@@ -1048,6 +1056,7 @@ local int AddUpgradeModifierBase(int uid,int attack_range,int sight_range,
     um->Modifier.Armor		= armor;
     um->Modifier.Speed		= speed;
     um->Modifier.HitPoints	= hit_points;
+    um->Modifier.RegenerationRate = regeneration_rate;
 
     for( i=0; i<MaxCosts; ++i ) {
 	um->Modifier.Costs[i]	= costs[i];
@@ -1424,6 +1433,7 @@ local void ApplyUpgradeModifier(Player * player, const UpgradeModifier * um)
 	    UnitTypes[z]->Stats[pn].Armor += um->Modifier.Armor;
 	    UnitTypes[z]->Stats[pn].Speed += um->Modifier.Speed;
 	    UnitTypes[z]->Stats[pn].HitPoints += um->Modifier.HitPoints;
+	    UnitTypes[z]->Stats[pn].RegenerationRate += um->Modifier.RegenerationRate;
 
 	    // upgrade costs :)
 	    for (j = 0; j < MaxCosts; ++j) {