This patch is supposed to allow modders to use more bonuses against
specific units.
It adds for the units.ruleset the following optional fields:
bonus_against_classX = "Class Name" - against which class we get
bonus. the X is a number from 1 to 4, so we can have different bonuses
against up to 4 different classes.
defense_bonusX = (percent value) - percent by which unit's defense is
increased against the class given in bonus_against_classX. Notice that
the X must be the same number. Also, negetive value will decrease our
defense. E.g - 100 will double our defense (adds it's full value to
itself), while -50 will halve it.
attack_bonusX = (percent value)
attack_firepowerX = (number) - The firepower when attacking that
class, the default is keeping the same firepower.
defense_firepowerX = (number) - As above, but when defending against that class.

I am sending this to the mailing list first because:
A. I am not sure my approach is good. It works, but it's not
nesseceraily the best solution.
B. The code on helpdata.c does not work, it always see NULL pointers,
altough everywhere else it doesn't happen.
diff -r -u trunk/ai/advmilitary.c trunk-class-bonus/ai/advmilitary.c
--- trunk/ai/advmilitary.c	2008-10-26 18:33:50.000000000 +0200
+++ trunk-class-bonus/ai/advmilitary.c	2008-12-22 13:19:16.000000000 +0200
@@ -488,6 +488,8 @@
 static unsigned int assess_danger(struct city *pcity)
 {
   int i;
+	int j;
+	int h = 0;
   unsigned int danger[DANGER_LAST];
   int defender;
   struct player *pplayer = city_owner(pcity);
@@ -496,6 +498,8 @@
   int igwall_threat = 0;
   struct tile *ptile = pcity->tile;
   int defense;
+#define MAX_DEFENSE_BONUS 8
+	struct unit_class *(defense_bonuses)[MAX_DEFENSE_BONUS];
 
   TIMING_LOG(AIT_DANGER, TIMER_START);
 
@@ -514,7 +518,19 @@
 
   unit_list_iterate(ptile->units, punit) {
     if (unit_has_type_flag(punit, F_DIPLOMAT)) pcity->ai.has_diplomat = TRUE;
+		/* Check if the defender has some bonus against any type at all */
+		int j;
+		for (j = 0; j <= CLASS_BONUS_MAX; j++) {
+			if (punit->utype->bonuses[j].class_bonus == NULL) {
+				continue;
+			} else {
+				if (punit->utype->bonuses[j].defense_bonus != 0) {
+					defense_bonuses[h] = punit->utype->bonuses[j].class_bonus;
+					h++;
+				}
+			}
+		}
   } unit_list_iterate_end;
 
   players_iterate(aplayer) {
@@ -567,14 +583,23 @@
       }
 
       if (unit_has_type_flag(punit, F_HORSE)) {
-	if (pikemen) {
-	  vulnerability /= 2;
-	} else {
-	  (void) ai_wants_role_unit(pplayer, pcity, F_PIKEMEN,
-				    vulnerability * move_rate /
-				    MAX(dist * 2, 1));
-	}
-      }
+				if (pikemen) {
+					vulnerability /= 2;
+				} else {
+					(void) ai_wants_role_unit(pplayer, pcity, F_PIKEMEN,
+									vulnerability * move_rate /
+									MAX(dist * 2, 1));
+				}
+      }
+
+			/* we check whether we have a unit with a bonus against that class
+			 * if so, we reduce vulnerability to half (regradless of the bonus)
+			 */
+			for (j = 0; j < h; j++) {
+				if (punit->utype->uclass == defense_bonuses[j]) {
+						vulnerability /= 2;
+						}
+					}
 
       if (unit_has_type_flag(punit, F_DIPLOMAT) && (dist <= 2 * move_rate)) {
 	pcity->ai.diplomat_threat = TRUE;
@@ -681,6 +706,7 @@
   int desire = punittype->hp;
   int attack = punittype->attack_strength;
   int defense = punittype->defense_strength;
+	int defense_bonus = 0;
 
   /* Sea and helicopters often have their firepower set to 1 when
    * defending. We can't have such units as defenders. */
@@ -699,6 +725,17 @@
   if (utype_has_flag(punittype, F_GAMELOSS)) {
     desire /= 10; /* but might actually be worth it */
   }
+	/* if unit has any defense bonus at all */
+	int i;
+	for (i = 0; i <= CLASS_BONUS_MAX; i++) {
+		if (punittype->bonuses[i].class_bonus == NULL) {
+			continue;
+		} else {
+			defense_bonus += punittype->bonuses[i].defense_bonus;
+		}
+	}
+	desire += (defense_bonus * defense) / 100;
+
   return desire;
 }
 
diff -r -u trunk/client/helpdata.c trunk-class-bonus/client/helpdata.c
--- trunk/client/helpdata.c	2008-11-21 07:54:27.000000000 +0200
+++ trunk-class-bonus/client/helpdata.c	2008-12-24 19:20:24.000000000 +0200
@@ -1012,6 +1012,51 @@
 		   " for the attacker.\n"),
 		 utype->bombard_rate);
   }
+	/* Get some information about unit bonuses */
+	int i;
+	for (i = 0; i < CLASS_BONUS_MAX; i++) {
+		if (utype->bonuses[i].class_bonus == NULL) {
+			continue;
+		} 
+		if (utype->bonuses[i].attack_bonus > 0) {
+			cat_snprintf(buf, bufsz,
+					_("* Gets %d percent attack bonus against units of %s class.\n"),
+					utype->bonuses[i].attack_bonus,
+					uclass_name_translation(utype->bonuses[i].class_bonus));
+		}
+		if (utype->bonuses[i].attack_bonus < 0) {
+			cat_snprintf(buf, bufsz,
+					_("* Gets %d percent attack penalty against units of %s class.\n"),
+					utype->bonuses[i].attack_bonus,
+					uclass_name_translation(utype->bonuses[i].class_bonus));
+		}
+		if (utype->bonuses[i].defense_bonus > 0) {
+			cat_snprintf(buf, bufsz,
+					_("* Gets %d percent defense bonus against units of %s class.\n"),
+					utype->bonuses[i].defense_bonus,
+					uclass_name_translation(utype->bonuses[i].class_bonus));
+		}
+		if (utype->bonuses[i].defense_bonus < 0) {
+			cat_snprintf(buf, bufsz,
+					_("* Gets %d percent defense penalty against units of %s class.\n"),
+					utype->bonuses[i].defense_bonus,
+					uclass_name_translation(utype->bonuses[i].class_bonus));
+		}
+		if (utype->bonuses[i].fp_defend != utype->firepower) {
+			cat_snprintf(buf, bufsz,
+					_("* Unit's firepower when defending against %s class units" 
+						" is %d.\n"),
+					uclass_name_translation(utype->bonuses[i].class_bonus),
+					utype->bonuses[i].fp_defend);
+		}
+		if (utype->bonuses[i].fp_attack != utype->firepower) {
+			cat_snprintf(buf, bufsz,
+					_("* The unit's firepower when attacking %s class units"
+						" is %d.\n"),
+					uclass_name_translation(utype->bonuses[i].class_bonus),
+					utype->bonuses[i].fp_attack);
+		}
+	}
   if (utype_has_flag(utype, F_AEGIS)) {
     CATLSTR(buf, bufsz,
 	    _("* Gets quintuple defense against missiles and aircraft.\n"));
diff -r -u trunk/common/combat.c trunk-class-bonus/common/combat.c
--- trunk/common/combat.c	2008-10-26 18:33:48.000000000 +0200
+++ trunk-class-bonus/common/combat.c	2009-01-02 09:11:16.000000000 +0200
@@ -294,6 +294,31 @@
     *att_fp = 1;
     *def_fp = 1;
   }
+
+	/* Check whether attacker has bonus against the defender's unit class */
+	int i;
+	for (i = 0; i <= CLASS_BONUS_MAX; i++) {
+		if (attacker->utype->bonuses[i].class_bonus == NULL) { /* no bonus... */
+			continue;
+		} else {
+			if (attacker->utype->bonuses[i].class_bonus == defender->utype->uclass) {
+				/* We have bonus against that kind of unit... */
+				*att_fp = attacker->utype->bonuses[i].fp_attack;
+			}
+		}
+	}
+
+	/* Check whether defender has bonus against the attacker's unit class */
+	for (i = 0; i <= CLASS_BONUS_MAX; i++) {
+		if (defender->utype->bonuses[i].class_bonus == NULL) { /* no bonus... */
+			continue;
+		} else {
+			if (defender->utype->bonuses[i].class_bonus == attacker->utype->uclass) {
+				/* We have bonus against that kind of unit... */
+				*def_fp = defender->utype->bonuses[i].fp_defend;
+			}
+		}
+	}
 }
 
 /**************************************************************************
@@ -412,8 +437,22 @@
 int get_total_attack_power(const struct unit *attacker,
 			   const struct unit *defender)
 {
+	int i;
   int attackpower = get_attack_power(attacker);
 
+	/* Check whether defender has bonus against the attacker's unit class */
+	for (i = 0; i <= CLASS_BONUS_MAX; i++) {
+		if (attacker->utype->bonuses[i].class_bonus == NULL) { /* no bonus... */
+			continue;
+		} else {
+			if (attacker->utype->bonuses[i].class_bonus == defender->utype->uclass) {
+				/* We have bonus against that kind of unit... */
+				attackpower += 
+					(attacker->utype->bonuses[i].attack_bonus * attackpower) / 100;
+			}
+		}
+	}
+
   return attackpower;
 }
 
@@ -461,6 +500,20 @@
     if (utype_has_flag(att_type, F_FIGHTER) && utype_has_flag(def_type, F_HELICOPTER)) {
       defensepower /= 2;
     }
+
+		/* Check whether unit has bonus against the attacker unit class */
+		int i;
+		for (i = 0; i <= CLASS_BONUS_MAX; i++) {
+			if (def_type->bonuses[i].class_bonus == NULL) { /* no bonus... */
+				continue;
+			} else {
+				if (def_type->bonuses[i].class_bonus == att_type->uclass) {
+					/* We have bonus against that kind of unit... */
+					defensepower += 
+				(def_type->bonuses[i].defense_bonus * defensepower) / 100;
+				}
+			}
+		}
   }
 
   if (tile_has_base_flag_for_unit(ptile, def_type, BF_DEFENSE_BONUS) && !pcity) {
trunk-class-bonus/common-ב קר אצמנ .combat.c.swp
diff -r -u trunk/common/unittype.h trunk-class-bonus/common/unittype.h
--- trunk/common/unittype.h	2008-10-21 16:25:02.000000000 +0200
+++ trunk-class-bonus/common/unittype.h	2008-12-24 11:31:28.000000000 +0200
@@ -84,7 +84,7 @@
   F_MARINES,     
   F_PARTIAL_INVIS,    /* Invisibile except when adjacent (Submarine) */   
   F_SETTLERS,         /* Does not include ability to found cities */
-  F_DIPLOMAT,    
+	F_DIPLOMAT,    
   F_TRIREME,          /* Trireme sinking effect */
   F_NUCLEAR,          /* Nuclear attack effect */
   F_SPY,              /* Enhanced spy abilities */
@@ -174,6 +174,21 @@
     int move_bonus;
 };
 
+/* We can define in here specific class against we get modified stats.
+ * For attack and defense we are giving a percent to add to our stat (or
+ * if negetive, decrease). For fire power (when attaking or defending) we
+ * give an absulote value. That way we can mimic all the F_HORSE/F_PIKEMEN
+ * kind of bonuses - YL
+ */
+#define CLASS_BONUS_MAX 4 
+struct  bonus_against_class {
+	struct unit_class *class_bonus;
+	int attack_bonus;
+	int defense_bonus;
+	int fp_defend;
+	int fp_attack;
+};
+
 struct unit_type {
   Unit_type_id item_number;
   struct name_translation name;
@@ -224,6 +239,8 @@
 
   bv_unit_classes targets; /* Can attack these classes even if they are otherwise "Unreachable" */
 
+	struct bonus_against_class bonuses[CLASS_BONUS_MAX];
+
   char *helptext;
 };
 
diff -r -u trunk/server/ruleset.c trunk-class-bonus/server/ruleset.c
--- trunk/server/ruleset.c	2008-12-11 10:25:50.000000000 +0200
+++ trunk-class-bonus/server/ruleset.c	2008-12-27 19:23:48.000000000 +0200
@@ -1283,7 +1283,39 @@
     u->paratroopers_mr_sub = SINGLE_MOVE * secfile_lookup_int_default(file,
         0, "%s.paratroopers_mr_sub", sec[i]);
     u->bombard_rate = secfile_lookup_int_default(file,
-	0, "%s.bombard_rate", sec[i]);
+				0, "%s.bombard_rate", sec[i]);
+
+		/* Setting bonuses against classes */
+		int h;
+		struct unit_class *bclass;
+		for (h = 0; h < CLASS_BONUS_MAX; h++) {
+			sval = secfile_lookup_str_default(file, NULL, 
+					"%s.bonus_against_class%d", sec[i], (h+1));
+			if (!sval) {
+				u->bonuses[h].class_bonus = NULL;
+			} else {
+				bclass = find_unit_class_by_rule_name(sval);
+				if (!bclass) {
+					ruleset_error(LOG_FATAL,
+												"\"%s\" unit_type \"%s\":"
+												"has unknown unit class %s as bonus against class.",
+												filename,
+												utype_rule_name(u),
+												slist[j]);
+				}
+				u->bonuses[h].class_bonus = bclass;
+			}
+
+			u->bonuses[h].attack_bonus = secfile_lookup_int_default(file, 0, 
+					"%s.attack_bonus%d", sec[i], (h + 1));
+			u->bonuses[h].defense_bonus = secfile_lookup_int_default(file, 0, 
+					"%s.defense_bonus%d", sec[i], (h + 1));
+			u->bonuses[h].fp_attack = secfile_lookup_int_default(file, 
+					u->firepower, "%s.attack_firepower%d", sec[i], (h + 1));
+			u->bonuses[h].fp_defend = secfile_lookup_int_default(file, 
+					u->firepower, "%s.defense_firepower%d", sec[i], (h + 1));
+		}
+
   } unit_type_iterate_end;
   
   /* flags */
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to