Feature #1546 » 3_4-specialist_unit.patch
client/helpdata.c | ||
---|---|---|
" %s initial population: %d.\n",
|
||
utype->city_size),
|
||
BULLET, utype->city_size);
|
||
if (is_super_specialist(utype->spec_type)) {
|
||
cat_snprintf(buf, bufsz,
|
||
/* TRANS: * ... Great Artist ... */
|
||
_(" %s the city starts with a %s superspecialist.\n"),
|
||
BULLET, specialist_plural_translation(utype->spec_type));
|
||
}
|
||
break;
|
||
case ACTRES_JOIN_CITY:
|
||
cat_snprintf(buf, bufsz,
|
||
/* TRANS: the %d is population. */
|
||
PL_(" %s max target size: %d.\n",
|
||
" %s max target size: %d.\n",
|
||
game.info.add_to_size_limit - utype->pop_cost),
|
||
BULLET, game.info.add_to_size_limit - utype->pop_cost);
|
||
cat_snprintf(buf, bufsz,
|
||
/* TRANS: the %d is the population added. */
|
||
PL_(" %s adds %d population.\n",
|
||
" %s adds %d population.\n",
|
||
utype->pop_cost),
|
||
BULLET, utype->pop_cost);
|
||
if (utype->pop_cost > 0 ){
|
||
cat_snprintf(buf, bufsz,
|
||
/* TRANS: the %d is population. */
|
||
PL_(" %s max target size: %d.\n",
|
||
" %s max target size: %d.\n",
|
||
game.info.add_to_size_limit - utype->pop_cost),
|
||
BULLET, game.info.add_to_size_limit - utype->pop_cost);
|
||
cat_snprintf(buf, bufsz,
|
||
/* TRANS: the %d is the population added. */
|
||
PL_(" %s adds %d population.\n",
|
||
" %s adds %d population.\n",
|
||
utype->pop_cost),
|
||
BULLET, utype->pop_cost);
|
||
}
|
||
if (is_super_specialist(utype->spec_type)) {
|
||
cat_snprintf(buf, bufsz,
|
||
/* TRANS: * ... Great Artist ... */
|
||
_(" %s adds a %s superspecialist to the city.\n"),
|
||
BULLET, specialist_plural_translation(utype->spec_type));
|
||
}
|
||
break;
|
||
case ACTRES_BOMBARD:
|
||
cat_snprintf(buf, bufsz,
|
client/packhand.c | ||
---|---|---|
u->uclass = uclass_by_number(p->unit_class_id);
|
||
u->build_cost = p->build_cost;
|
||
u->pop_cost = p->pop_cost;
|
||
u->spec_type = specialist_by_number(p->spectype_id);
|
||
u->attack_strength = p->attack_strength;
|
||
u->defense_strength = p->defense_strength;
|
||
u->move_rate = p->move_rate;
|
common/actions.c | ||
---|---|---|
#include "oblig_reqs.h"
|
||
#include "research.h"
|
||
#include "server_settings.h"
|
||
#include "specialist.h"
|
||
#include "unit.h"
|
||
... | ... | |
{
|
||
switch (paction->result) {
|
||
case ACTRES_JOIN_CITY:
|
||
if (actor_unittype->pop_cost <= 0) {
|
||
/* Reason: Must have population to add. */
|
||
if (actor_unittype->pop_cost <= 0 && !is_super_specialist(actor_unittype->spec_type)) {
|
||
/* Reason: Must have something to add. */
|
||
return FALSE;
|
||
}
|
||
break;
|
common/actres.c | ||
---|---|---|
#include "movement.h"
|
||
#include "player.h"
|
||
#include "requirements.h"
|
||
#include "specialist.h"
|
||
#include "tile.h"
|
||
#include "traderoutes.h"
|
||
... | ... | |
case ACTRES_JOIN_CITY:
|
||
{
|
||
int new_pop;
|
||
Specialist_type_id sid;
|
||
if (!omniscient
|
||
&& !player_can_see_city_externals(actor->player, target->city)) {
|
||
... | ... | |
* VisibleByOthers. */
|
||
return TRI_NO;
|
||
}
|
||
sid = specialist_index(unit_type_get(actor->unit)->spec_type);
|
||
if (DEFAULT_SPECIALIST != sid) {
|
||
if (!city_can_use_specialist(target->city, sid)) {
|
||
/* Respect specialist reqs */
|
||
/* Potential info leak about if they are fulfilled */
|
||
return TRI_NO;
|
||
}
|
||
if (is_super_specialist_id(sid)
|
||
&& target->city->specialists[sid] >= MAX_CITY_SIZE) {
|
||
/* No place to add a superspecialist */
|
||
/* Info leak on city superspecialists but it happens too rarely */
|
||
return TRI_NO;
|
||
}
|
||
}
|
||
}
|
||
break;
|
common/networking/packets.def | ||
---|---|---|
UINT8 unit_class_id;
|
||
UINT16 build_cost;
|
||
UINT8 pop_cost;
|
||
UINT8 spectype_id;
|
||
UINT8 attack_strength;
|
||
UINT8 defense_strength;
|
||
MOVEFRAGS move_rate;
|
common/unittype.h | ||
---|---|---|
int build_cost; /* Use wrappers to access this. */
|
||
int pop_cost; /* Number of workers the unit contains
|
||
* (e.g., settlers, engineers) */
|
||
struct specialist *spec_type; /* affects only founding and adding to cities */
|
||
int attack_strength;
|
||
int defense_strength;
|
||
int move_rate;
|
server/ruleset/ruleload.c | ||
---|---|---|
"%s.city_slots", sec_name);
|
||
u->city_size = secfile_lookup_int_default(file, 1,
|
||
"%s.city_size", sec_name);
|
||
if ((sval = secfile_lookup_str(file, "%s.specialist", sec_name))) {
|
||
if (!(u->spec_type = specialist_by_rule_name(sval))) {
|
||
ruleset_error(nullptr, LOG_ERROR,
|
||
"\"%s\" unit_type \"%s\":"
|
||
" bad specialist \"%s\".",
|
||
filename, utype_rule_name(u), sval);
|
||
ok = FALSE;
|
||
}
|
||
} else {
|
||
/* Specialists must have been processed before */
|
||
fc_assert_action(DEFAULT_SPECIALIST >= 0
|
||
&& specialist_by_number(DEFAULT_SPECIALIST),
|
||
ok = FALSE; break);
|
||
u->spec_type = specialist_by_number(DEFAULT_SPECIALIST);
|
||
}
|
||
sval = secfile_lookup_str_default(file, transp_def_type_name(TDT_ALIGHT),
|
||
"%s.tp_defense", sec_name);
|
||
... | ... | |
packet.unit_class_id = uclass_number(utype_class(u));
|
||
packet.build_cost = u->build_cost;
|
||
packet.pop_cost = u->pop_cost;
|
||
packet.spectype_id = specialist_index(u->spec_type);
|
||
packet.attack_strength = u->attack_strength;
|
||
packet.defense_strength = u->defense_strength;
|
||
packet.move_rate = u->move_rate;
|
server/unithand.c | ||
---|---|---|
{
|
||
int amount = unit_pop_value(punit);
|
||
const struct unit_type *act_utype;
|
||
Specialist_type_id spec_id = DEFAULT_SPECIALIST;
|
||
/* Sanity check: The actor is still alive. */
|
||
fc_assert_ret_val(punit, FALSE);
|
||
... | ... | |
/* Sanity check: The target city still exists. */
|
||
fc_assert_ret_val(pcity, FALSE);
|
||
fc_assert_ret_val(amount > 0, FALSE);
|
||
city_size_add(pcity, amount);
|
||
if (is_super_specialist(act_utype->spec_type)) {
|
||
Specialist_type_id sspec = specialist_index(act_utype->spec_type);
|
||
fc_assert_ret_val(pcity->specialists[sspec] < MAX_CITY_SIZE, FALSE);
|
||
pcity->specialists[sspec]++;
|
||
} else {
|
||
fc_assert_ret_val(amount > 0, FALSE);
|
||
/* Hardly much needed but let it be */
|
||
spec_id = specialist_index(act_utype->spec_type);
|
||
}
|
||
/* Make the new people something, otherwise city fails the checks */
|
||
pcity->specialists[DEFAULT_SPECIALIST] += amount;
|
||
fc_assert_ret_val(MAX_CITY_SIZE - pcity->specialists[spec_id] >= amount,
|
||
FALSE);
|
||
pcity->specialists[spec_id] += amount;
|
||
citizens_update(pcity, unit_nationality(punit));
|
||
/* Refresh the city data. */
|
||
city_refresh(pcity);
|
||
... | ... | |
struct player *nationality;
|
||
struct player *towner;
|
||
const struct unit_type *act_utype;
|
||
Specialist_type_id sid;
|
||
struct city *pcity;
|
||
/* Sanity check: The actor still exists. */
|
||
fc_assert_ret_val(pplayer, FALSE);
|
||
... | ... | |
}
|
||
act_utype = unit_type_get(punit);
|
||
sid = specialist_index(act_utype->spec_type);
|
||
nationality = unit_nationality(punit);
|
||
create_city(pplayer, ptile, name, nationality);
|
||
size = unit_type_get(punit)->city_size;
|
||
if (size > 1) {
|
||
struct city *pcity = tile_city(ptile);
|
||
fc_assert_ret_val(pcity != NULL, FALSE);
|
||
city_change_size(pcity, size, nationality, -1, nullptr);
|
||
size = act_utype->city_size;
|
||
pcity = tile_city(ptile); /* A callback may destroy or replace it any time */
|
||
if (nullptr != pcity) {
|
||
if (is_super_specialist_id(sid) && pcity->specialists[sid] < MAX_CITY_SIZE) {
|
||
pcity->specialists[sid]++;
|
||
}
|
||
if (size > 1) {
|
||
city_change_size(pcity, size, nationality, -1, nullptr);
|
||
}
|
||
}
|
||
/* May cause an incident even if the target tile is unclaimed. A ruleset
|
tools/ruleutil/rulesave.c | ||
---|---|---|
secfile_insert_int(sfile, put->build_cost, "%s.build_cost", path);
|
||
secfile_insert_int(sfile, put->pop_cost, "%s.pop_cost", path);
|
||
if (DEFAULT_SPECIALIST < 0 || DEFAULT_SPECIALIST != specialist_index(put->spec_type)) {
|
||
secfile_insert_str(sfile, specialist_rule_name(put->spec_type),
|
||
"%s.specialist", path);
|
||
}
|
||
secfile_insert_int(sfile, put->attack_strength, "%s.attack", path);
|
||
secfile_insert_int(sfile, put->defense_strength, "%s.defense", path);
|
||
secfile_insert_int(sfile, put->move_rate / SINGLE_MOVE, "%s.move_rate", path);
|