Project

Profile

Help

HostedRedmine.com has moved to the Planio platform. All logins and passwords remained the same. All users will be able to login and use Redmine just as before. Read more...

Feature #913055 » 0001-Detailed-combat-info-from-server-message.patch

Charlie Galik, 2021-01-05 09:16 PM

View differences:

common/combat.c
return NULL;
}
/**************************************************************************
Returns if the attack is going to be a tired attack
**************************************************************************/
bool is_tired_attack(int moves_left)
{
return game.info.tired_attack && moves_left < SINGLE_MOVE;
}
/**************************************************************************
Convenience wrapper for base_get_attack_power.
**************************************************************************/
......
power = punittype->attack_strength * POWER_FACTOR
* vlevel->power_fact / 100;
if (game.info.tired_attack && moves_left < SINGLE_MOVE) {
if (is_tired_attack(moves_left)) {
power = (power * moves_left) / SINGLE_MOVE;
}
common/combat.h
bool unit_really_ignores_citywalls(const struct unit *punit);
struct city *sdi_try_defend(const struct player *owner,
const struct tile *ptile);
bool is_tired_attack(int moves_left);
int get_attack_power(const struct unit *punit);
int base_get_attack_power(const struct unit_type *punittype,
common/featured_text.c
return buf;
}
/**************************************************************************
Get a text of a unit's vet level.
N.B.: The returned string is static, so every call to this function
overwrites the previous.
**************************************************************************/
const char *unit_veteran_level_string(const struct unit *punit)
{
static char buf[MAX_LEN_LINK];
const struct veteran_system *vsystem;
const struct veteran_level *vlevel;
if (!punit) {
fc_snprintf(buf, sizeof(buf), ""); //if no unit, return empty string
return buf;
}
vsystem = utype_veteran_system(unit_type_get(punit));
vlevel = utype_veteran_level(unit_type_get(punit), punit->veteran);
fc_snprintf(buf, sizeof(buf), "%s", name_translation_get(&vlevel->name));
return buf;
}
/**************************************************************************
Get string of unit's firepower text, i.e. "FP:2 "
If firepower is equal to one, then an empty string is returned
so as to shorten the text output.
N.B.: The returned string is static, so every call to this function
overwrites the previous.
**************************************************************************/
const char *unit_firepower_if_not_one(int firepower)
{
static char buf[MAX_LEN_LINK];
if (firepower == 1) {
fc_snprintf(buf, sizeof(buf), "");
} else {
fc_snprintf(buf, sizeof(buf), "FP:%d ", firepower);
}
return buf;
}
/**************************************************************************
Get a text link to an unit.
N.B.: The returned string is static, so every call to this function
common/featured_text.h
const char *tile_link(const struct tile *ptile);
const char *unit_link(const struct unit *punit);
const char *unit_tile_link(const struct unit *punit);
const char *unit_veteran_level_string(const struct unit *punit);
const char *unit_firepower_if_not_one(int firepower);
#ifdef __cplusplus
}
server/unithand.c
#include "city.h"
#include "combat.h"
#include "events.h"
#include "featured_text.h"
#include "game.h"
#include "log.h"
#include "map.h"
......
static void unit_attack_handling(struct unit *punit, struct unit *pdefender)
{
char loser_link[MAX_LEN_LINK], winner_link[MAX_LEN_LINK];
char attacker_link[MAX_LEN_LINK], defender_link[MAX_LEN_LINK];
char combat_msg[MAX_LEN_MSG];
struct unit *ploser, *pwinner;
struct city *pcity;
int moves_used, def_moves_used;
......
bool adj;
enum direction8 facing;
int att_hp, def_hp;
int att_hp_start = punit->hp;
int def_hp_start = pdefender->hp;
int def_power = get_total_defense_power(punit, pdefender);
int att_power = get_total_attack_power(punit, pdefender);
int def_fp, att_fp;
get_modified_firepower(punit, pdefender, &att_fp, &def_fp);
log_debug("Start attack: %s %s against %s %s.",
nation_rule_name(nation_of_player(pplayer)),
......
old_unit_vet = punit->veteran;
old_defender_vet = pdefender->veteran;
/* N.B.: unit_link always returns the same pointer. */
sz_strlcpy(attacker_link, unit_tile_link(punit));
sz_strlcpy(defender_link, unit_tile_link(pdefender));
if (is_tired_attack(punit->moves_left)) {
fc_snprintf(combat_msg, sizeof(combat_msg),
/* TRANS: "Combat: veteran 1 German Cannon [id:100 tired
* attack:6.1 ... HP:20] has a 55.69% the green Polish
* Phalanx [id:99 defense:3.5 ... HP:10]." */
_("Combat: %s %s %s [id:%d tired attack:%.1g %sHP:%d] has "
"a %.4g%% chance against the %s %s %s [id:%d defense:%.1g"
" %sHP:%d]."),
unit_veteran_level_string(punit),
nation_adjective_for_player(unit_owner(punit)),
attacker_link,
punit->id,
(float)att_power/POWER_FACTOR,
unit_firepower_if_not_one(att_fp),
att_hp_start,
unit_win_chance(punit, pdefender)*100,
unit_veteran_level_string(pdefender),
nation_adjective_for_player(unit_owner(pdefender)),
defender_link,
pdefender->id,
(float)def_power/POWER_FACTOR,
unit_firepower_if_not_one(def_fp),
def_hp_start);
} else {
fc_snprintf(combat_msg, sizeof(combat_msg),
/* TRANS: "Combat: veteran 1 German Cannon [id:100
* attack:6.1 ... HP:20] has a 55.69% the green Polish
* Phalanx [id:99 defense:3.5 ... HP:10]." */
_("Combat: %s %s %s [id:%d attack:%.1g %sHP:%d] has a "
"%.4g%% chance against the %s %s %s [id:%d defense:%.1g"
" %sHP:%d]."),
unit_veteran_level_string(punit),
nation_adjective_for_player(unit_owner(punit)),
attacker_link,
punit->id,
(float)att_power/POWER_FACTOR,
unit_firepower_if_not_one(att_fp),
att_hp_start,
unit_win_chance(punit, pdefender)*100,
unit_veteran_level_string(pdefender),
nation_adjective_for_player(unit_owner(pdefender)),
defender_link,
pdefender->id,
(float)def_power/POWER_FACTOR,
unit_firepower_if_not_one(def_fp),
def_hp_start);
}
unit_versus_unit(punit, pdefender, FALSE, &att_hp, &def_hp);
/* Now can send correct notification for lost/won */
notify_player(unit_owner(pdefender), unit_tile(pdefender),
(punit->hp > 0) ? E_UNIT_LOST_DEF : E_UNIT_WIN,
ftc_server, "%s", combat_msg);
notify_player(unit_owner(punit), unit_tile(punit),
(punit->hp > 0) ? E_UNIT_WIN_ATT : E_UNIT_LOST_ATT,
ftc_server, "%s", combat_msg);
if ((att_hp <= 0 || uclass_has_flag(unit_class_get(punit), UCF_MISSILE))
&& unit_transported(punit)) {
/* Dying attacker must be first unloaded so it doesn't die insider transport */
......
nation_rule_name(nation_of_unit(pdefender)),
unit_rule_name(pdefender));
notify_player(unit_owner(pwinner), unit_tile(pwinner),
E_UNIT_WIN, ftc_server,
/* TRANS: "Your Cannon ... the Polish Destroyer." */
_("Your %s survived the pathetic attack from the %s %s."),
winner_link,
nation_adjective_for_player(unit_owner(ploser)),
loser_link);
if (vet) {
notify_unit_experience(pwinner);
}
notify_player(unit_owner(ploser), def_tile,
E_UNIT_LOST_ATT, ftc_server,
/* TRANS: "... Cannon ... the Polish Destroyer." */
_("Your attacking %s failed against the %s %s!"),
loser_link,
nation_adjective_for_player(unit_owner(pwinner)),
winner_link);
fc_snprintf(combat_msg, sizeof(combat_msg),
/* TRANS: "Combat result: German Cannon attack failed
* against the Polish Destroyer [lost 27 HP, 3 HP
* remaining and achieved the rank of <veteran level>]."
*/
_("Combat result: %s %s attack failed against the %s %s"
" [lost %d HP, %d HP remaining and achieved the rank of"
" %s]."),
nation_adjective_for_player(unit_owner(punit)),
attacker_link,
nation_adjective_for_player(unit_owner(pdefender)),
defender_link,
def_hp_start - pdefender->hp,
pdefender->hp,
unit_veteran_level_string(pdefender));
} else {
fc_snprintf(combat_msg, sizeof(combat_msg),
/* TRANS: "Combat result: German Cannon attack failed
* against the Polish Destroyer [lost 27 HP, 3 HP
* remaining]."
*/
_("Combat result: %s %s attack failed against the %s %s "
"[lost %d HP, %d HP remaining]."),
nation_adjective_for_player(unit_owner(punit)),
attacker_link,
nation_adjective_for_player(unit_owner(pdefender)),
defender_link,
def_hp_start - pdefender->hp,
pdefender->hp);
}
notify_player(unit_owner(pdefender), unit_tile(pdefender), E_UNIT_WIN,
ftc_server, "%s", combat_msg);
notify_player(unit_owner(punit), unit_tile(punit), E_UNIT_LOST_ATT,
ftc_server, "%s", combat_msg);
wipe_unit(ploser, ULR_KILLED, unit_owner(pwinner));
} else {
/* The defender lost, the attacker punit lives! */
......
nation_rule_name(nation_of_unit(pdefender)),
unit_rule_name(pdefender));
if (vet) {
fc_snprintf(combat_msg, sizeof(combat_msg),
/* TRANS: "Combat result: German Cannon attack succeeded
* against the Polish Destroyer. German Cannon lost 19 HP,
* 1 HP remaining and achieved the rank of
* <veteran level>]." */
_("Combat result: %s %s attack succeeded against the %s "
"%s. %s %s lost %d HP, has %d HP remaining"
" and achieved the rank of %s."),
nation_adjective_for_player(unit_owner(punit)),
winner_link,
nation_adjective_for_player(unit_owner(pdefender)),
loser_link,
nation_adjective_for_player(unit_owner(punit)),
winner_link,
att_hp_start - pwinner->hp,
pwinner->hp,
unit_veteran_level_string(punit));
} else {
fc_snprintf(combat_msg, sizeof(combat_msg),
/* TRANS: "Combat result: German Cannon attack succeeded
* against the Polish Destroyer. German Cannon lost 19 HP
* and 1 HP remaining." */
_("Combat result: %s %s attack succeeded against the %s "
"%s. %s %s lost %d HP and has %d HP remaining."),
nation_adjective_for_player(unit_owner(punit)),
winner_link,
nation_adjective_for_player(unit_owner(pdefender)),
loser_link,
nation_adjective_for_player(unit_owner(punit)),
winner_link,
att_hp_start - pwinner->hp,
pwinner->hp);
}
notify_player(unit_owner(pdefender), unit_tile(pdefender),
E_UNIT_LOST_DEF, ftc_server, "%s", combat_msg);
notify_player(unit_owner(punit), unit_tile(punit),
E_UNIT_WIN_ATT, ftc_server, "%s", combat_msg);
punit->moved = TRUE; /* We moved */
kill_unit(pwinner, ploser,
vet && !uclass_has_flag(unit_class_get(punit), UCF_MISSILE));
server/unittools.c
}
if (!is_stack_vulnerable(unit_tile(punit)) || unitcount == 1) {
notify_player(pvictor, unit_tile(pkiller), E_UNIT_WIN_ATT, ftc_server,
/* TRANS: "... Cannon ... the Polish Destroyer." */
_("Your attacking %s succeeded against the %s %s!"),
pkiller_link,
nation_adjective_for_player(pvictim),
punit_link);
if (vet) {
notify_unit_experience(pkiller);
}
notify_player(pvictim, unit_tile(punit), E_UNIT_LOST_DEF, ftc_server,
/* TRANS: "Cannon ... the Polish Destroyer." */
_("%s lost to an attack by the %s %s."),
punit_link,
nation_adjective_for_player(pvictor),
pkiller_link);
wipe_unit(punit, ULR_KILLED, pvictor);
} else { /* unitcount > 1 */
int i;
......
}
} unit_list_iterate_end;
/* Inform the destroyer: lots of different cases here! */
notify_player(pvictor, unit_tile(pkiller), E_UNIT_WIN_ATT, ftc_server,
/* TRANS: "... Cannon ... the Polish Destroyer ...." */
PL_("Your attacking %s succeeded against the %s %s "
"(and %d other unit)!",
"Your attacking %s succeeded against the %s %s "
"(and %d other units)!", unitcount - 1),
pkiller_link,
nation_adjective_for_player(pvictim),
punit_link,
unitcount - 1);
if (vet) {
notify_unit_experience(pkiller);
/* Inform the destroyer again if more than one unit was killed */
if (unitcount > 1) {
notify_player(pvictor, unit_tile(pkiller), E_UNIT_WIN_ATT, ftc_server,
/* TRANS: "... Cannon ... the Polish Destroyer ...." */
PL_("Your attacking %s succeeded against the %s %s "
"(and %d other unit)!",
"Your attacking %s succeeded against the %s %s "
"(and %d other units)!", unitcount - 1),
pkiller_link,
nation_adjective_for_player(pvictim),
punit_link,
unitcount - 1);
}
/* inform the owners: this only tells about owned units that were killed.
(1-1/12)