diff -Nur -Xfreecivdiff.ignore freeciv-cvs/client/gui-gtk/gotodlg.c freeciv-patched/client/gui-gtk/gotodlg.c --- freeciv-cvs/client/gui-gtk/gotodlg.c 2003-07-10 11:53:39.000000000 +0100 +++ freeciv-patched/client/gui-gtk/gotodlg.c 2003-07-24 17:00:25.000000000 +0100 @@ -198,7 +198,7 @@ if(!all_cities && i!=game.player_idx) continue; city_list_iterate(game.players[i].cities, pcity) { sz_strlcpy(name, pcity->name); - if (pcity->improvements[B_AIRPORT] == I_ACTIVE) + if (pcity->airlift) sz_strlcat(name, "(A)"); gtk_clist_append( GTK_CLIST( goto_list ), row ); } diff -Nur -Xfreecivdiff.ignore freeciv-cvs/client/gui-gtk-2.0/gotodlg.c freeciv-patched/client/gui-gtk-2.0/gotodlg.c --- freeciv-cvs/client/gui-gtk-2.0/gotodlg.c 2003-07-10 11:53:39.000000000 +0100 +++ freeciv-patched/client/gui-gtk-2.0/gotodlg.c 2003-07-24 17:00:25.000000000 +0100 @@ -259,7 +259,7 @@ gtk_list_store_set(store, &it, 0, pcity->name, - 1, (pcity->improvements[B_AIRPORT] == I_ACTIVE), + 1, pcity->airlift, -1); } city_list_iterate_end; diff -Nur -Xfreecivdiff.ignore freeciv-cvs/client/gui-mui/gotodlg.c freeciv-patched/client/gui-mui/gotodlg.c --- freeciv-cvs/client/gui-mui/gotodlg.c 2003-07-10 11:53:39.000000000 +0100 +++ freeciv-patched/client/gui-mui/gotodlg.c 2003-07-24 17:00:25.000000000 +0100 @@ -58,7 +58,7 @@ { static char name[80]; sz_strlcpy(name, pcity->name); - if (pcity->improvements[B_AIRPORT] == I_ACTIVE) + if (pcity->airlift) sz_strlcat(name, "(A)"); *array = name; } diff -Nur -Xfreecivdiff.ignore freeciv-cvs/client/gui-win32/gotodlg.c freeciv-patched/client/gui-win32/gotodlg.c --- freeciv-cvs/client/gui-win32/gotodlg.c 2003-07-10 11:53:39.000000000 +0100 +++ freeciv-patched/client/gui-win32/gotodlg.c 2003-07-24 17:00:25.000000000 +0100 @@ -189,7 +189,7 @@ if(!show_all_cities && i!=game.player_idx) continue; city_list_iterate(game.players[i].cities, pcity) { sz_strlcpy(name, pcity->name); - if (pcity->improvements[B_AIRPORT] == I_ACTIVE) + if (pcity->airlift) sz_strlcat(name, "(A)"); j=ListBox_AddString(list,name); ListBox_SetItemData(list,j,pcity->id); diff -Nur -Xfreecivdiff.ignore freeciv-cvs/client/gui-xaw/gotodlg.c freeciv-patched/client/gui-xaw/gotodlg.c --- freeciv-cvs/client/gui-xaw/gotodlg.c 2003-07-10 11:53:39.000000000 +0100 +++ freeciv-patched/client/gui-xaw/gotodlg.c 2003-07-24 17:00:25.000000000 +0100 @@ -223,7 +223,7 @@ city_list_iterate(game.players[i].cities, pcity) { char name[MAX_LEN_NAME+3]; sz_strlcpy(name, pcity->name); - if (pcity->improvements[B_AIRPORT] == I_ACTIVE) + if (pcity->airlift) sz_strlcat(name, "(A)"); city_name_ptrs[j++]=mystrdup(name); } diff -Nur -Xfreecivdiff.ignore freeciv-cvs/common/city.c freeciv-patched/common/city.c --- freeciv-cvs/common/city.c 2003-07-24 17:00:25.000000000 +0100 +++ freeciv-patched/common/city.c 2003-07-24 17:00:25.000000000 +0100 @@ -1790,6 +1790,7 @@ gov = get_gov_pcity(pcity); city_init_tile_mods(pcity); + pcity->airlift = FALSE; city_map_iterate(x, y) { struct tile_type *type; @@ -1868,6 +1869,8 @@ forcecontentpct = forcecontentpct * amount / 100; break; case EFT_FORCE_HAPPY: forcehappy += amount; break; + case EFT_AIRLIFT: + pcity->airlift = TRUE; break; default: break; } diff -Nur -Xfreecivdiff.ignore freeciv-cvs/common/unit.c freeciv-patched/common/unit.c --- freeciv-cvs/common/unit.c 2003-07-24 16:58:28.000000000 +0100 +++ freeciv-patched/common/unit.c 2003-07-24 17:00:25.000000000 +0100 @@ -38,9 +38,6 @@ This function calculates the move rate of the unit taking into account the penalty for reduced hitpoints (affects sea and land units only) and the effects of wonders for sea units. - -FIXME: Use generalised improvements code instead of hardcoded -wonder effects --RK ***************************************************************/ int unit_move_rate(struct unit *punit) { @@ -49,20 +46,13 @@ switch (unit_type(punit)->move_type) { case LAND_MOVING: move_rate = (move_rate * punit->hp) / unit_type(punit)->hp; + move_rate += punit->move_modifier; break; case SEA_MOVING: move_rate = (move_rate * punit->hp) / unit_type(punit)->hp; + move_rate += punit->move_modifier; - if (player_owns_active_wonder(unit_owner(punit), B_LIGHTHOUSE)) { - move_rate += SINGLE_MOVE; - } - - if (player_owns_active_wonder(unit_owner(punit), B_MAGELLAN)) { - move_rate += (improvement_variant(B_MAGELLAN) == 1) - ? SINGLE_MOVE : 2 * SINGLE_MOVE; - } - if (player_knows_techs_with_flag(unit_owner(punit), TF_BOAT_FAST)) { move_rate += SINGLE_MOVE; } @@ -74,6 +64,7 @@ case HELI_MOVING: case AIR_MOVING: + move_rate += punit->move_modifier; break; default: @@ -1466,7 +1457,10 @@ punit->foul = FALSE; punit->fuel = unit_type(punit)->fuel; punit->hp = unit_type(punit)->hp; + punit->move_modifier = 0; + punit->hp_recover = 0; punit->moves_left = unit_move_rate(punit); + punit->moved = FALSE; punit->paradropped = FALSE; punit->connecting = FALSE; diff -Nur -Xfreecivdiff.ignore freeciv-cvs/common/unit.h freeciv-patched/common/unit.h --- freeciv-cvs/common/unit.h 2003-07-24 16:58:28.000000000 +0100 +++ freeciv-patched/common/unit.h 2003-07-24 17:00:25.000000000 +0100 @@ -129,6 +129,8 @@ } goto_dest; int activity_count; enum tile_special_type activity_target; + int hp_recover; /* hp to recover each turn (if -1, full recover) */ + int move_modifier; /* moves bonus from Lighthouse, Magellan etc. */ enum unit_focus_status focus_status; int ord_map, ord_city; /* ord_map and ord_city are the order index of this unit in tile.units diff -Nur -Xfreecivdiff.ignore freeciv-cvs/server/citytools.c freeciv-patched/server/citytools.c --- freeciv-cvs/server/citytools.c 2003-07-24 16:59:50.000000000 +0100 +++ freeciv-patched/server/citytools.c 2003-07-24 17:00:25.000000000 +0100 @@ -509,15 +509,26 @@ **************************************************************************/ bool do_make_unit_veteran(struct city *pcity, Unit_Type_id id) { + Unit_Class_id uclass; + enum tile_terrain_type tile_t; + enum tile_special_type spec_t; + if (unit_type_flag(id, F_DIPLOMAT)) return government_has_flag(get_gov_pcity(pcity), G_BUILD_VETERAN_DIPLOMAT); - if (is_ground_unittype(id) || improvement_variant(B_BARRACKS)==1) - return city_got_barracks(pcity); - else if (is_water_unit(id)) - return (city_affected_by_wonder(pcity, B_LIGHTHOUSE) || city_got_building(pcity, B_PORT)); - else - return city_got_building(pcity, B_AIRPORT); + /* Fill in the particulars of the new unit, and the city */ + uclass = get_unittype_class(id); + tile_t = map_get_terrain(pcity->x, pcity->y); + spec_t = map_get_special(pcity->x, pcity->y); + + /* Do we have any veteran-making effects? */ + city_effects_iterate_full(iter, pcity, uclass, tile_t, spec_t) { + if (iter.imeff->type == EFT_UNIT_VETERAN) { + return TRUE; + } + } city_effects_iterate_full_end; + + return FALSE; } /************************************************************************** diff -Nur -Xfreecivdiff.ignore freeciv-cvs/server/cityturn.c freeciv-patched/server/cityturn.c --- freeciv-cvs/server/cityturn.c 2003-07-21 13:58:27.000000000 +0100 +++ freeciv-patched/server/cityturn.c 2003-07-24 17:00:25.000000000 +0100 @@ -1368,10 +1368,6 @@ pcity->did_sell=FALSE; pcity->did_buy = FALSE; - if (city_got_building(pcity, B_AIRPORT)) - pcity->airlift=TRUE; - else - pcity->airlift=FALSE; update_tech(pplayer, pcity->science_total); pplayer->economic.gold+=pcity->tax_total; pay_for_units(pplayer, pcity); diff -Nur -Xfreecivdiff.ignore freeciv-cvs/server/savegame.c freeciv-patched/server/savegame.c --- freeciv-cvs/server/savegame.c 2003-07-24 16:59:50.000000000 +0100 +++ freeciv-patched/server/savegame.c 2003-07-24 17:00:25.000000000 +0100 @@ -2213,6 +2213,13 @@ if (!game.is_new_game) { /* Set active city improvements/wonders and their effects */ update_all_effects(); + + /* Make sure the move/hitpoint modifiers are set */ + players_iterate(pplayer) { + unit_list_iterate(pplayer->units, punit) { + unit_update_modifiers(pplayer, punit); + } unit_list_iterate_end; + } players_iterate_end; } game.player_idx=0; diff -Nur -Xfreecivdiff.ignore freeciv-cvs/server/unittools.c freeciv-patched/server/unittools.c --- freeciv-cvs/server/unittools.c 2003-07-21 13:58:28.000000000 +0100 +++ freeciv-patched/server/unittools.c 2003-07-24 17:00:25.000000000 +0100 @@ -70,7 +70,8 @@ static struct unit *choose_more_important_refuel_target(struct unit *punit1, struct unit *punit2); static bool maybe_cancel_patrol_due_to_enemy(struct unit *punit); -static int hp_gain_coord(struct unit *punit); +static int hp_gain_coord(struct unit *punit, struct city *pcity, + bool fullrepair); /************************************************************************** returns a unit type with a given role, use -1 if you don't want a tech @@ -110,12 +111,19 @@ **************************************************************************/ void maybe_make_veteran(struct unit *punit) { + int amount = 50; /* Normally there's a 50% chance... */ + if (punit->veteran) return; - if (player_owns_active_wonder(unit_owner(punit), B_SUNTZU)) - punit->veteran = TRUE; - else - punit->veteran = (myrand(2) == 1); + + /* Do we have any veteran-making effects? */ + unit_effects_iterate(iter, punit) { + if (iter.imeff->type == EFT_UNIT_VET_COMBAT) { + amount = MAX(amount, iter.imeff->amount); + } + } unit_effects_iterate_end; + + punit->veteran = (myrand(100) < amount ? 1 : 0); } /************************************************************************** @@ -418,6 +426,9 @@ unit_list_iterate(pplayer->units, punit) { + /* Set relevant hp/move modifiers from generalised improvements */ + unit_update_modifiers(pplayer, punit); + /* 2) Modify unit hitpoints. Helicopters can even lose them. */ unit_restore_hitpoints(pplayer, punit); @@ -506,6 +517,36 @@ } /**************************************************************************** + Apply hitpoint and move modifiers to the given unit, to save on + recalculation every time we update moverate/hitpoints +*****************************************************************************/ +void unit_update_modifiers(struct player *pplayer, struct unit *punit) +{ + bool fullrepair = FALSE; + int hp_recover = 0, move_modifier = 0; + + /* Add effects of generalised improvements */ + unit_effects_iterate(iter, punit) { + switch(iter.imeff->type) { + case EFT_UNIT_REPAIR: + fullrepair = TRUE; + break; + case EFT_UNIT_RECOVER: + hp_recover += iter.imeff->amount; + break; + case EFT_UNIT_MOVE: + move_modifier += iter.imeff->amount; + break; + default: + break; + } + } unit_effects_iterate_end; + + punit->hp_recover = (fullrepair ? -1 : hp_recover); + punit->move_modifier = move_modifier * SINGLE_MOVE; +} + +/**************************************************************************** add hitpoints to the unit, hp_gain_coord returns the amount to add united nations will speed up the process by 2 hp's / turn, means helicopters will actually not loose hp's every turn if player have that wonder. @@ -515,18 +556,19 @@ static void unit_restore_hitpoints(struct player *pplayer, struct unit *punit) { bool was_lower; + struct city *pcity = map_get_city(punit->x, punit->y); + bool fullrepair = (punit->hp_recover == -1); was_lower=(punit->hp < unit_type(punit)->hp); if(!punit->moved) { - punit->hp+=hp_gain_coord(punit); + punit->hp += hp_gain_coord(punit, pcity, fullrepair); } - if (player_owns_active_wonder(pplayer, B_UNITED)) - punit->hp+=2; - + /* hp_recover is set by unit_update_modifiers */ + if (!fullrepair) punit->hp += punit->hp_recover; + if(is_heli_unit(punit)) { - struct city *pcity = map_get_city(punit->x,punit->y); if(!pcity) { if (!map_has_special(punit->x, punit->y, S_AIRBASE)) punit->hp-=unit_type(punit)->hp/10; @@ -572,27 +614,19 @@ ports will regen navalunits completely fortify will add a little extra. ***************************************************************************/ -static int hp_gain_coord(struct unit *punit) +static int hp_gain_coord(struct unit *punit, struct city *pcity, + bool fullrepair) { int hp; - struct city *pcity; if (unit_on_fortress(punit)) hp=unit_type(punit)->hp/4; else hp=0; - if((pcity=map_get_city(punit->x,punit->y))) { - if ((city_got_barracks(pcity) && - (is_ground_unit(punit) || improvement_variant(B_BARRACKS)==1)) || - (city_got_building(pcity, B_AIRPORT) && is_air_unit(punit)) || - (city_got_building(pcity, B_AIRPORT) && is_heli_unit(punit)) || - (city_got_building(pcity, B_PORT) && is_sailing_unit(punit))) { - hp=unit_type(punit)->hp; - } - else - hp=unit_type(punit)->hp/3; - } - else if (!is_heli_unit(punit)) + if (pcity) { + hp = fullrepair ? unit_type(punit)->hp : unit_type(punit)->hp / 3; + } else if (!is_heli_unit(punit)) { hp++; + } if(punit->activity==ACTIVITY_FORTIFIED) hp++; @@ -1490,9 +1524,14 @@ punit->hp = hp_left; } + /* Apply/remove effects of Magellan etc. */ + unit_update_modifiers(pplayer, punit); + if (moves_left >= 0) { /* Override default full MP */ punit->moves_left = moves_left; + } else { + punit->moves_left = unit_move_rate(punit); } /* Assume that if moves_left < 0 then the unit is "fresh", diff -Nur -Xfreecivdiff.ignore freeciv-cvs/server/unittools.h freeciv-patched/server/unittools.h --- freeciv-cvs/server/unittools.h 2003-07-10 11:53:39.000000000 +0100 +++ freeciv-patched/server/unittools.h 2003-07-24 17:00:25.000000000 +0100 @@ -35,6 +35,7 @@ void update_unit_activities(struct player *pplayer); /* various */ +void unit_update_modifiers(struct player *pplayer, struct unit *punit); char *get_location_str_in(struct player *pplayer, int x, int y); char *get_location_str_at(struct player *pplayer, int x, int y); enum goto_move_restriction get_activity_move_restriction(enum unit_activity activity);