DESCRIPTION This patch adds an invulnerability cheat to Battle for Wesnoth 1.2.8. With this patch, the wesnoth binary honours the following environment variables : DEATHLESS_SIDES=num[,num]... Value is interpreted as a list of side numbers separated by white space or commas. All units on any of specified sides are unkillable. DEATHLESS_TEAM=str Value is interpreted as a team name. All units on the specified team are unkillable. "Unkillable" means that the hit points of the unit never drop below 1, no matter how much damage it takes. EXAMPLE Start the game with units from teams "One", 2 and 4 unkillable : DEATHLESS_SIDES=2,4 DEATHLESS_TEAM=One ./wesnoth NOTES The team names for DEATHLESS_TEAM can be difficult to infer. The matching is case-sensitive and the names shown in the in-game stats table sometimes have a different case than the internal variables against which the value of DEATHLESS_TEAM is compared. When playing against the computer, DEATHLESS_SIDES=1 is a good first guess. Dwarvish Ulfserkers make wonderful recruits with this cheat. Because they have the "berserk" weapon special, they are practically guaranteed to end the turn with at least one empty hex around them. Thus, a pair of DU working together is unstoppable : on odd turns, DU #1 cleans the hex in front of DU #2 so DU #2 can advance and vice-versa on even turns. Unkillable units make enemy magnets. Because they look like easy prey (hit points stuck at 1), the AI tends to keep sending units against them, neglecting other concerns such as securing more villages. -- AYM 2008-01-20 diff -ur wesnoth-1.2.8/src/unit.cpp wesnoth-1.2.8-aym1/src/unit.cpp --- wesnoth-1.2.8/src/unit.cpp 2007-02-23 18:17:44.000000000 +0100 +++ wesnoth-1.2.8-aym1/src/unit.cpp 2008-01-04 16:37:13.000000000 +0100 @@ -786,9 +786,97 @@ } } +/* AYM 2007-12-29 */ +#include + +static const char deathless_sides_name[] = "DEATHLESS_SIDES"; +static const char deathless_team_name[] = "DEATHLESS_TEAM"; + +static long deathless_sides_bitmap = 1 << 31; +static const char *deathless_team_inval = ""; +static const char *deathless_team = deathless_team_inval; + +static void get_cheats () +{ + + /* Parse $DEATHLESS_SIDES */ + if (deathless_sides_bitmap == 1 << 31) + { + const char *s = getenv (deathless_sides_name); + deathless_sides_bitmap = 0; + if (s == NULL) + { + fprintf (stderr, "%s not set\n", deathless_sides_name); + } + else + { + fprintf (stderr, "%s set to \"%s\"\n", deathless_sides_name, s); + for (const char *p = s; *p != '\0';) + { + char *p2; + errno = 0; + long n = strtol (p, &p2, 0); + if (errno != 0) + { + fprintf (stderr, "%s(%d): %s\n", deathless_sides_name, int (p - s), strerror (errno)); + break; + } + fprintf (stderr, "%s(%d): parsed \"%.*s\" as %ld\n", deathless_sides_name, int (p - s), int (p2 - p), p, n); + if (n < 1) + fprintf (stderr, "%s(%d): side# < 1 (%ld)\n", deathless_sides_name, int (p - s), n); + else if (n >= 31) + fprintf (stderr, "%s(%d): side# >= 31 (%ld)\n", deathless_sides_name, int (p - s), n); + else + deathless_sides_bitmap |= (1 << n); + p = p2; + while (*p == ',' || isspace (*p)) + p++; + } + fprintf (stderr, "%s: %#lx\n", deathless_sides_name, deathless_sides_bitmap); + } + } + + if (deathless_team == deathless_team_inval) + { + deathless_team = getenv (deathless_team_name); + if (deathless_team == NULL) + fprintf (stderr, "%s not set\n", deathless_team_name); + else + fprintf (stderr, "%s set to \"%s\"\n", deathless_team_name, deathless_team); + } +} + bool unit::take_hit(int damage) { + get_cheats (); + fprintf (stderr, + "take_hit: name \"%s\", desc \"%s\", cu_ \"%s\"," + " side %u, team_name \"%s\", user_ \"%s\"\n" + , name_.c_str () + , description_.c_str () + , custom_unit_description_.c_str () + , side () + , (*teams_)[side_ - 1].team_name ().c_str () + , (*teams_)[side_ - 1].user_team_name ().c_str () + ); hit_points_ -= damage; + if (hit_points_ < 1) + { + const char *reason = NULL; + if (side_ < 31 && (deathless_sides_bitmap & (1 << side_))) + reason = deathless_sides_name; + else if (deathless_team != NULL + && ( strcmp (deathless_team, custom_unit_description_.c_str ()) == 0 + || strcmp (deathless_team, (*teams_)[side_ - 1].team_name ().c_str ()) == 0 + || strcmp (deathless_team, (*teams_)[side_ - 1].user_team_name ().c_str ()) == 0)) + reason = deathless_team_name; + if (reason != NULL) + { + fprintf (stderr, "%s would have died (%d), saved because of %s\n", + custom_unit_description_.c_str (), hit_points_, reason); + hit_points_ = 1; + } + } return hit_points_ <= 0; } void unit::heal(int amount)