diff -Nur -Xfreecivdiff.ignore freeciv-cvs/client/packhand.c freeciv-patched/client/packhand.c --- freeciv-cvs/client/packhand.c 2003-07-24 17:04:53.000000000 +0100 +++ freeciv-patched/client/packhand.c 2003-07-24 17:04:54.000000000 +0100 @@ -1409,9 +1409,14 @@ bool poptechup, new_tech = FALSE; char msg[MAX_LEN_MSG]; struct player *pplayer = &game.players[pinfo->playerno]; + bool govnation_changed = FALSE; sz_strlcpy(pplayer->name, pinfo->name); + if (pplayer->nation != pinfo->nation + || pplayer->government != pinfo->government) { + govnation_changed = TRUE; + } pplayer->nation=pinfo->nation; pplayer->is_male=pinfo->is_male; pplayer->team = pinfo->team; @@ -1500,6 +1505,11 @@ append_output_window(msg); } } + + if (govnation_changed) { + player_update_global_effects(pplayer); + update_all_effects(); + } if (pplayer == game.player_ptr && (pplayer->revolution < 1 || pplayer->revolution > 5) && @@ -2305,6 +2315,7 @@ gov->ruler_titles = fc_calloc(gov->num_ruler_titles, sizeof(struct ruler_title)); + gov->effect = p->effect; /* pointer assignment */ gov->helptext = p->helptext; /* pointer assignment */ tilespec_setup_government(p->id); @@ -2440,6 +2451,7 @@ pl->leaders[i].is_male = p->leader_sex[i]; } pl->city_style = p->city_style; + pl->effect = p->effect; /* pointer assignment */ if (p->class[0] != '\0') { pl->class = mystrdup(p->class); diff -Nur -Xfreecivdiff.ignore freeciv-cvs/common/game.c freeciv-patched/common/game.c --- freeciv-cvs/common/game.c 2003-07-24 17:04:53.000000000 +0100 +++ freeciv-patched/common/game.c 2003-07-24 17:04:54.000000000 +0100 @@ -618,6 +618,7 @@ static void deactivate_all_effects(void) { deactivate_effects(get_geff_parent(get_eff_world())); + deactivate_effects(&game.destroyed_effects); players_iterate(pplayer) { int contid; @@ -629,6 +630,7 @@ city_list_iterate(pplayer->cities, pcity) { deactivate_effects(get_eff_city(pcity)); } city_list_iterate_end; + deactivate_effects(&pplayer->destroyed_effects); } players_iterate_end; freelog(LOG_DEBUG, "All effects deactivated"); diff -Nur -Xfreecivdiff.ignore freeciv-cvs/common/government.c freeciv-patched/common/government.c --- freeciv-cvs/common/government.c 2003-07-24 17:04:53.000000000 +0100 +++ freeciv-patched/common/government.c 2003-07-24 17:04:54.000000000 +0100 @@ -302,6 +302,9 @@ ***************************************************************/ static void government_free(struct government *gov) { + free(gov->effect); + gov->effect = NULL; + free(gov->ruler_titles); gov->ruler_titles = NULL; diff -Nur -Xfreecivdiff.ignore freeciv-cvs/common/improvement.c freeciv-patched/common/improvement.c --- freeciv-cvs/common/improvement.c 2003-07-24 17:04:53.000000000 +0100 +++ freeciv-patched/common/improvement.c 2003-07-24 17:04:54.000000000 +0100 @@ -19,6 +19,7 @@ #include #include "game.h" +#include "government.h" #include "log.h" #include "map.h" #include "mem.h" @@ -1036,16 +1037,6 @@ return TRUE; } -struct impr_effect *get_base_effect(Impr_Type_id impr, struct player *pplayer) -{ - return improvement_types[impr].effect; -} - -const char *get_effect_cause_name(Impr_Type_id impr, struct player *pplayer) -{ - return get_improvement_name(impr); -} - /************************************************************************** Sets an effect iterator to the start of the effect lists - common function used by other effect iterator initialisation functions @@ -1133,6 +1124,33 @@ eff_iterator_start(iter); } +struct impr_effect *get_base_effect(Impr_Type_id impr, struct player *pplayer) +{ + switch(impr) { + case B_NATION: + return get_nation_by_plr(pplayer)->effect; + case B_GOV: + return get_gov_pplayer(pplayer)->effect; + default: + break; + } + return improvement_types[impr].effect; +} + +const char *get_effect_cause_name(Impr_Type_id impr, struct player *pplayer) +{ + switch(impr) { + case B_NATION: + return pplayer ? get_nation_name(pplayer->nation) : "unknown nation"; + case B_GOV: + return pplayer ? get_government_name(pplayer->government) + : "unknown government"; + default: + break; + } + return get_improvement_name(impr); +} + /************************************************************************** Given an initialised effect iterator, returns the next active effect. iter->imeff also points to this effect (the data is in the ruleset, so @@ -1181,11 +1199,17 @@ /* Make sure we don't return the same effect again */ iter->imeff++; iter->bitmask <<= 1; } else { - iter->imeff = improvement_types[effect->impr].effect; + iter->imeff = get_base_effect(effect->impr, iter->pplayer); iter->bitmask = 1; } for (; iter->imeff && iter->imeff->type != EFT_LAST; iter->imeff++, iter->bitmask <<= 1) { + if (iter->imeff->range == iter->range) { + freelog(LOG_DEBUG, "Effect iteration: effect %s at range %s", + effect_type_name(iter->imeff->type), + effect_range_name(iter->range)); + } + if (effect->active & iter->bitmask && iter->imeff->range == iter->range && (iter->imeff->range != EFR_LOCAL @@ -1326,39 +1350,70 @@ **************************************************************************/ void add_destroyed_improvement(struct player *p, Impr_Type_id id) { - struct impr_effect *eff; - struct geff_vector *globeff[2] = { NULL, NULL }; struct ceff_vector *desteff; struct eff_city *ceff; - int i; game.destroyed_owner[id] = p; freelog(LOG_DEBUG, "Adding destroyed improvement %s to %s", improvement_types[id].name, p ? p->name : "global list"); - for (eff = improvement_types[id].effect; - eff && eff->type != EFT_LAST; eff++) { - if (eff->survives) { - if (eff->range == EFR_WORLD) { - globeff[1] = get_eff_world(); - } else if (eff->range == EFR_PLAYER && p) { - globeff[0] = get_eff_player(p); - } - } - } desteff = (p ? &p->destroyed_effects : &game.destroyed_effects); ceff = append_ceff(desteff); ceff->impr = id; ceff->active = 0; + add_global_effects(id, p); +} + +static void get_global_effects(Impr_Type_id impr, struct player *pplayer, + struct geff_vector *globeff[]) +{ + struct impr_effect *imeff; + + globeff[0] = globeff[1] = NULL; + for (imeff = get_base_effect(impr, pplayer); + imeff && imeff->type != EFT_LAST; ++imeff) { + if (imeff->range == EFR_WORLD) { + globeff[1] = get_eff_world(); + } else if (imeff->range == EFR_PLAYER) { + globeff[0] = get_eff_player(pplayer); + } + } +} + +void remove_global_effects(Impr_Type_id impr, struct player *pplayer) +{ + struct geff_vector *globeff[2]; + int i, effind; + + get_global_effects(impr, pplayer, globeff); + for (i = 0; i < 2; ++i) { + if (globeff[i]) { + for (effind = 0; effind < geff_vector_size(globeff[i]); ++effind) { + struct eff_global *eff = geff_vector_get(globeff[i], effind); + + if (eff->cityid == -1 && eff->eff.impr == impr && eff->plr == pplayer) { + eff->eff.impr = B_LAST; + } + } + } + } +} + +void add_global_effects(Impr_Type_id impr, struct player *pplayer) +{ + struct geff_vector *globeff[2]; + int i; - for (i = 0; i < 2; i++) { + get_global_effects(impr, pplayer, globeff); + for (i = 0; i < 2; ++i) { if (globeff[i]) { struct eff_global *geff; geff = append_geff(globeff[i]); - geff->eff.impr = id; + geff->eff.impr = impr; geff->eff.active = 0; geff->cityid = -1; + geff->plr = pplayer; } } } diff -Nur -Xfreecivdiff.ignore freeciv-cvs/common/improvement.h freeciv-patched/common/improvement.h --- freeciv-cvs/common/improvement.h 2003-07-24 17:04:53.000000000 +0100 +++ freeciv-patched/common/improvement.h 2003-07-24 17:04:54.000000000 +0100 @@ -83,6 +83,9 @@ IR_LAST /* keep this last */ }; +#define B_NATION (B_LAST + 1) +#define B_GOV (B_LAST + 2) + /* Range of effects (used in equiv_range and effect.range fields) * These must correspond to effect_range_names[] in improvement.c. */ enum effect_range { @@ -210,7 +213,10 @@ struct eff_city { Impr_Type_id impr; /* The ID of the improvement that confers the effects; * if B_LAST, then this instance is unused and ready - * to be freed (or replaced with a new improvement */ + * to be freed (or replaced with a new improvement); + * if B_NATION or B_GOV, then the effects are not + * from an improvement at all, but are conferred by + * the nation or governement type */ Eff_Status active; /* Which of the actual impr_effect effects are active */ }; @@ -408,6 +414,8 @@ Impr_Type_id get_improvement_for_effect(struct player *pplayer, enum effect_type id, struct unit_classes *aff_unit); +struct impr_effect *get_base_effect(Impr_Type_id impr, struct player *pplayer); +const char *get_effect_cause_name(Impr_Type_id impr, struct player *pplayer); /* player related improvement and unit functions */ bool could_player_eventually_build_improvement(struct player *p, @@ -421,13 +429,13 @@ struct geff_vector *get_eff_player(struct player *plr); struct geff_vector *get_eff_island(int cont, struct player *plr); struct ceff_vector *get_eff_city(struct city *pcity); +void remove_global_effects(Impr_Type_id impr, struct player *pplayer); +void add_global_effects(Impr_Type_id impr, struct player *pplayer); void allot_island_improvs(void); void improvements_update_obsolete(void); void improvements_update_redundant(struct player *pplayer, struct city *pcity, int cont, enum impr_range range); -struct impr_effect *get_base_effect(Impr_Type_id impr, struct player *pplayer); -const char *get_effect_cause_name(Impr_Type_id impr, struct player *pplayer); /* Iterates over all improvements. Creates a new variable names m_i * with type Impr_Type_id which holds the id of the current improvement. */ diff -Nur -Xfreecivdiff.ignore freeciv-cvs/common/nation.c freeciv-patched/common/nation.c --- freeciv-cvs/common/nation.c 2003-07-10 11:53:35.000000000 +0100 +++ freeciv-patched/common/nation.c 2003-07-24 17:04:54.000000000 +0100 @@ -208,6 +208,9 @@ int i; struct nation_type *p = get_nation_by_idx(nation); + free(p->effect); + p->effect = NULL; + for (i = 0; i < p->leader_count; i++) { free(p->leaders[i].name); } diff -Nur -Xfreecivdiff.ignore freeciv-cvs/common/nation.h freeciv-patched/common/nation.h --- freeciv-cvs/common/nation.h 2003-07-18 13:40:03.000000000 +0100 +++ freeciv-patched/common/nation.h 2003-07-24 17:04:54.000000000 +0100 @@ -35,6 +35,7 @@ struct Sprite; /* opaque; client-gui specific */ struct player; +struct impr_effect; enum advisor_type {ADV_ISLAND, ADV_MILITARY, ADV_TRADE, ADV_SCIENCE, ADV_FOREIGN, ADV_ATTITUDE, ADV_DOMESTIC, ADV_LAST}; @@ -97,6 +98,8 @@ /* civilized was never implemented, but will be eventually. -- Syela */ int advisors[ADV_LAST]; /* never implemented either. -- Syela */ + struct impr_effect *effect; /* list; .type==EFT_LAST terminated */ + /* Following basically disabled -- Syela */ /* Note the client doesn't use/have these. */ struct { diff -Nur -Xfreecivdiff.ignore freeciv-cvs/common/packets.c freeciv-patched/common/packets.c --- freeciv-cvs/common/packets.c 2003-07-24 17:04:53.000000000 +0100 +++ freeciv-patched/common/packets.c 2003-07-24 17:04:54.000000000 +0100 @@ -2649,6 +2649,10 @@ dio_put_string(&dout, packet->graphic_str); dio_put_string(&dout, packet->graphic_alt); + if (has_capability("impr_gen", pc->capability)) { + dio_put_effects(&dout, packet->effect); + } + /* This must be last, so client can determine length: */ if(packet->helptext) { dio_put_string(&dout, packet->helptext); @@ -2742,6 +2746,13 @@ dio_get_string(&din, packet->graphic_str, sizeof(packet->graphic_str)); dio_get_string(&din, packet->graphic_alt, sizeof(packet->graphic_alt)); + if (has_capability("impr_gen", pc->capability)) { + dio_get_effects(&din, &packet->effect); + } else { + packet->effect = fc_malloc(sizeof(struct impr_effect)); + packet->effect[0].type = EFT_LAST; + } + len = dio_input_remaining(&din); if (len > 0) { packet->helptext = fc_malloc(len); @@ -2792,6 +2803,9 @@ } dio_put_uint8(&dout, packet->city_style); dio_put_tech_list(&dout, packet->init_techs); + if (has_capability("impr_gen", pc->capability)) { + dio_put_effects(&dout, packet->effect); + } if (has_capability("class_legend", pc->capability)) { dio_put_string(&dout, packet->class); dio_put_string(&dout, packet->legend); @@ -2829,6 +2843,9 @@ dio_get_uint8(&din, &packet->city_style); dio_get_tech_list(&din, packet->init_techs); + if (has_capability("impr_gen", pc->capability)) { + dio_get_effects(&din, &packet->effect); + } if (has_capability("class_legend", pc->capability)) { dio_get_string(&din, packet->class, sizeof(packet->class)); dio_get_string(&din, packet->legend, sizeof(packet->legend)); diff -Nur -Xfreecivdiff.ignore freeciv-cvs/common/packets.h freeciv-patched/common/packets.h --- freeciv-cvs/common/packets.h 2003-07-24 17:04:53.000000000 +0100 +++ freeciv-patched/common/packets.h 2003-07-24 17:04:54.000000000 +0100 @@ -805,6 +805,7 @@ char graphic_str[MAX_LEN_NAME]; char graphic_alt[MAX_LEN_NAME]; + struct impr_effect *effect; char *helptext; /* same as for packet_ruleset_unit, above */ }; @@ -828,6 +829,7 @@ bool leader_sex[MAX_NUM_LEADERS]; int city_style; int init_techs[MAX_NUM_TECH_LIST]; + struct impr_effect *effect; char class[MAX_LEN_NAME]; char legend[MAX_LEN_MSG]; }; diff -Nur -Xfreecivdiff.ignore freeciv-cvs/common/player.c freeciv-patched/common/player.c --- freeciv-cvs/common/player.c 2003-07-24 17:04:39.000000000 +0100 +++ freeciv-patched/common/player.c 2003-07-24 17:04:54.000000000 +0100 @@ -25,6 +25,7 @@ #include "government.h" #include "idex.h" #include "improvement.h" +#include "log.h" #include "map.h" #include "mem.h" #include "rand.h" @@ -620,3 +621,38 @@ { return TEST_BIT(me->gives_shared_vision, them->player_no); } + +void player_update_global_effects(struct player *pplayer) +{ + struct ceff_vector *ceff; + struct eff_city *eff; + int effind; + + freelog(LOG_DEBUG, "player_update_global_effects: " + "player %s nation %s gov %s", pplayer->name, + get_nation_name(pplayer->nation), + get_government_name(pplayer->government)); + ceff = &pplayer->destroyed_effects; + + /* First, remove any existing effects */ + for (effind = 0; effind < ceff_vector_size(ceff); ++effind) { + eff = ceff_vector_get(ceff, effind); + + if (eff->impr == B_NATION || eff->impr == B_GOV) { + remove_global_effects(eff->impr, pplayer); + eff->impr = B_LAST; + } + } + + ceff = &pplayer->destroyed_effects; + + eff = append_ceff(ceff); + eff->impr = B_NATION; + eff->active = 0; + add_global_effects(eff->impr, pplayer); + + eff = append_ceff(ceff); + eff->impr = B_GOV; + eff->active = 0; + add_global_effects(eff->impr, pplayer); +} diff -Nur -Xfreecivdiff.ignore freeciv-cvs/common/player.h freeciv-patched/common/player.h --- freeciv-cvs/common/player.h 2003-07-24 17:04:40.000000000 +0100 +++ freeciv-patched/common/player.h 2003-07-24 17:04:54.000000000 +0100 @@ -272,6 +272,7 @@ bool is_barbarian(const struct player *pplayer); bool gives_shared_vision(struct player *me, struct player *them); +void player_update_global_effects(struct player *pplayer); #define players_iterate(PI_player) \ { \ diff -Nur -Xfreecivdiff.ignore freeciv-cvs/server/citytools.c freeciv-patched/server/citytools.c --- freeciv-cvs/server/citytools.c 2003-07-24 17:04:54.000000000 +0100 +++ freeciv-patched/server/citytools.c 2003-07-24 17:04:54.000000000 +0100 @@ -987,17 +987,17 @@ pcity->id = get_next_id_number(); idex_register_city(pcity); - if (!pplayer->capital) { - pplayer->capital = TRUE; - city_add_improvement(pcity, B_PALACE); - } - /* Before arranging workers to show unknown land */ map_unfog_pseudo_city_area(pplayer, x, y); map_set_city(x, y, pcity); city_list_insert(&pplayer->cities, pcity); + if (!pplayer->capital) { + pplayer->capital = TRUE; + city_add_improvement(pcity, B_PALACE); + update_all_effects(); + } add_city_to_minimap(x, y); /* Update the national borders. */ diff -Nur -Xfreecivdiff.ignore freeciv-cvs/server/plrhand.c freeciv-patched/server/plrhand.c --- freeciv-cvs/server/plrhand.c 2003-07-24 17:04:40.000000000 +0100 +++ freeciv-patched/server/plrhand.c 2003-07-24 17:04:54.000000000 +0100 @@ -778,6 +778,9 @@ } check_player_government_rates(pplayer); + player_update_global_effects(pplayer); + update_all_effects(); + global_city_refresh(pplayer); send_player_info(pplayer, pplayer); } diff -Nur -Xfreecivdiff.ignore freeciv-cvs/server/ruleset.c freeciv-patched/server/ruleset.c --- freeciv-cvs/server/ruleset.c 2003-07-24 17:04:54.000000000 +0100 +++ freeciv-patched/server/ruleset.c 2003-07-24 17:04:54.000000000 +0100 @@ -686,7 +686,7 @@ **************************************************************************/ static struct impr_effect *load_effects(const char *secname, const char *name, struct section_file *file, - bool unit_effects) + bool unit_effects, bool all_survive) { int count, j, k; char *item; @@ -758,8 +758,12 @@ e->amount = secfile_lookup_int_default(file, 0, "%s.effect%d.amount", secname, j); - e->survives = secfile_lookup_int_default(file, 0, "%s.effect%d.survives", - secname, j); + if (all_survive) { + e->survives = 1; + } else { + e->survives = secfile_lookup_int_default(file, 0, "%s.effect%d.survives", + secname, j); + } item = secfile_lookup_str_default(file, "", "%s.effect%d.cond_bldg", secname, j); @@ -991,7 +995,7 @@ u->food_cost = secfile_lookup_int(file, "%s.uk_food", sec[i]); u->gold_cost = secfile_lookup_int(file, "%s.uk_gold", sec[i]); - u->effect = load_effects(sec[i], u->name, file, TRUE); + u->effect = load_effects(sec[i], u->name, file, TRUE, FALSE); u->helptext = lookup_helptext(file, sec[i]); } unit_type_iterate_end; @@ -1323,7 +1327,7 @@ b->sabotage = secfile_lookup_int(file, "%s.sabotage", sec[i]); - b->effect = load_effects(sec[i], b->name, file, FALSE); + b->effect = load_effects(sec[i], b->name, file, FALSE, FALSE); /* FIXME: remove when gen-impr obsoletes */ b->variant = secfile_lookup_int_default(file, 0, "%s.variant", sec[i]); @@ -1744,7 +1748,7 @@ g->celeb_food_before_penalty = secfile_lookup_int(file, "%s.production_food_penalty,1", sec[i]); - g->effect = load_effects(sec[i], g->name, file, FALSE); + g->effect = load_effects(sec[i], g->name, file, FALSE, TRUE); g->helptext = lookup_helptext(file, sec[i]); } government_iterate_end; @@ -2342,6 +2346,8 @@ } pl->goals.government = val; + pl->effect = load_effects(sec[i], pl->name, file, FALSE, TRUE); + /* read "normal" city names */ pl->city_names = load_city_name_list(file, sec[i], ".cities"); @@ -2808,6 +2814,7 @@ sz_strlcpy(gov.graphic_str, g->graphic_str); sz_strlcpy(gov.graphic_alt, g->graphic_alt); + gov.effect = g->effect; /* pointer assignment */ gov.helptext = g->helptext; /* pointer assignment */ lsend_packet_ruleset_government(dest, &gov); @@ -2857,6 +2864,8 @@ sz_strlcpy(packet.class, n->class); sz_strlcpy(packet.legend, n->legend); + packet.effect = n->effect; /* pointer assignment */ + lsend_packet_ruleset_nation(dest, &packet); } } diff -Nur -Xfreecivdiff.ignore freeciv-cvs/server/savegame.c freeciv-patched/server/savegame.c --- freeciv-cvs/server/savegame.c 2003-07-24 17:04:40.000000000 +0100 +++ freeciv-patched/server/savegame.c 2003-07-24 17:04:54.000000000 +0100 @@ -2249,6 +2249,10 @@ } if (!game.is_new_game) { + players_iterate(pplayer) { + player_update_global_effects(pplayer); + } players_iterate_end; + /* Set active city improvements/wonders and their effects */ update_all_effects(); diff -Nur -Xfreecivdiff.ignore freeciv-cvs/server/srv_main.c freeciv-patched/server/srv_main.c --- freeciv-cvs/server/srv_main.c 2003-07-24 17:02:27.000000000 +0100 +++ freeciv-patched/server/srv_main.c 2003-07-24 17:04:54.000000000 +0100 @@ -1733,6 +1733,7 @@ init_tech(pplayer, game.tech); player_limit_to_government_rates(pplayer); pplayer->economic.gold = game.gold; + player_update_global_effects(pplayer); } players_iterate_end; game.max_players = game.nplayers;