? ddddd ? fastwar ? server_autoattack.diff ? server_autoattack2.diff ? server_autoattack3.diff ? unitsforattack.gz ? server/.unittools.c.swp Index: client/control.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/client/control.c,v retrieving revision 1.86 diff -u -r1.86 control.c --- client/control.c 2002/11/14 09:14:50 1.86 +++ client/control.c 2002/11/18 19:36:30 @@ -643,6 +643,17 @@ unit_list_iterate_end; } +void wakeup_auto_attack_unit(int x, int y) +{ + unit_list_iterate(map_get_tile(x,y)->units, punit) { + if(punit->activity==ACTIVITY_AUTO_ATTACK + && game.player_idx==punit->owner) { + request_new_unit_activity(punit, ACTIVITY_IDLE); + } + } + unit_list_iterate_end; +} + /************************************************************************** Player pressed 'b' or otherwise instructed unit to build or add to city. If the unit can build a city, we popup the appropriate dialog. @@ -893,6 +904,16 @@ } /**************************************************************** +... server "a"uto attack +*****************************************************************/ +void request_unit_auto_attack(struct unit *punit) +{ + if(punit->activity!=ACTIVITY_AUTO_ATTACK && + can_unit_do_activity(punit, ACTIVITY_AUTO_ATTACK)) + request_new_unit_activity(punit, ACTIVITY_AUTO_ATTACK); +} + +/**************************************************************** ... *****************************************************************/ void request_unit_fortify(struct unit *punit) @@ -1580,17 +1601,6 @@ /************************************************************************** ... **************************************************************************/ -void key_unit_auto_attack(void) -{ - if(get_unit_in_focus()) - if(!unit_flag(punit_focus, F_SETTLERS) && - can_unit_do_auto(punit_focus)) - request_unit_auto(punit_focus); -} - -/************************************************************************** -... -**************************************************************************/ void key_unit_auto_explore(void) { if(get_unit_in_focus()) @@ -1718,6 +1728,16 @@ if(get_unit_in_focus()) if(can_unit_do_activity(punit_focus, ACTIVITY_SENTRY)) request_new_unit_activity(punit_focus, ACTIVITY_SENTRY); +} + +/************************************************************************** +We use the new activity AUTO_ATTACK for that. +**************************************************************************/ +void key_unit_auto_attack(void) +{ + if(get_unit_in_focus()) + if(can_unit_do_activity(punit_focus, ACTIVITY_AUTO_ATTACK)) + request_new_unit_activity(punit_focus, ACTIVITY_AUTO_ATTACK); } /************************************************************************** Index: client/control.h =================================================================== RCS file: /home/freeciv/CVS/freeciv/client/control.h,v retrieving revision 1.29 diff -u -r1.29 control.h --- client/control.h 2002/11/01 17:51:12 1.29 +++ client/control.h 2002/11/18 19:36:30 @@ -146,6 +146,7 @@ void key_unit_pollution(void); void key_unit_road(void); void key_unit_sentry(void); +void key_unit_auto_attack(void); void key_unit_traderoute(void); void key_unit_transform(void); void key_unit_unload(void); Index: client/tilespec.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/client/tilespec.c,v retrieving revision 1.89 diff -u -r1.89 tilespec.c --- client/tilespec.c 2002/11/17 02:21:11 1.89 +++ client/tilespec.c 2002/11/18 19:36:31 @@ -1157,6 +1157,9 @@ case ACTIVITY_SENTRY: s = sprites.unit.sentry; break; + case ACTIVITY_AUTO_ATTACK: + s = sprites.unit.auto_attack; + break; case ACTIVITY_GOTO: s = sprites.unit.go_to; break; Index: client/gui-gtk/menu.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk/menu.c,v retrieving revision 1.70 diff -u -r1.70 menu.c --- client/gui-gtk/menu.c 2002/11/14 09:14:54 1.70 +++ client/gui-gtk/menu.c 2002/11/18 19:36:32 @@ -105,6 +105,7 @@ MENU_ORDER_POLLUTION, /* shared with PARADROP */ MENU_ORDER_FALLOUT, MENU_ORDER_SENTRY, + MENU_ORDER_AUTO_ATTACK, MENU_ORDER_PILLAGE, MENU_ORDER_HOMECITY, MENU_ORDER_UNLOAD, @@ -354,6 +355,9 @@ case MENU_ORDER_SENTRY: key_unit_sentry(); break; + case MENU_ORDER_AUTO_ATTACK: + key_unit_auto_attack(); + break; case MENU_ORDER_PILLAGE: key_unit_pillage(); break; @@ -368,7 +372,10 @@ break; case MENU_ORDER_AUTO_SETTLER: if(get_unit_in_focus()) - request_unit_auto(get_unit_in_focus()); + if (is_military_unit(get_unit_in_focus())) + key_unit_auto_attack(); + else + request_unit_auto(get_unit_in_focus()); break; case MENU_ORDER_AUTO_EXPLORE: key_unit_auto_explore(); @@ -662,6 +669,8 @@ NULL, 0, "" }, { "/" N_("Orders") "/" N_("_Sentry"), "s", orders_menu_callback, MENU_ORDER_SENTRY }, +{ "/" N_("Orders") "/" N_("Server _auto attack"), NULL, + orders_menu_callback, MENU_ORDER_AUTO_ATTACK }, { "/" N_("Orders") "/" N_("Pillage"), "p", orders_menu_callback, MENU_ORDER_PILLAGE }, { "/" N_("Orders") "/sep2", NULL, Index: common/unit.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/common/unit.c,v retrieving revision 1.165 diff -u -r1.165 unit.c --- common/unit.c 2002/11/15 21:24:30 1.165 +++ common/unit.c 2002/11/18 19:36:33 @@ -500,7 +500,7 @@ { if (unit_flag(punit, F_SETTLERS)) return TRUE; - if (is_military_unit(punit) && map_get_city(punit->x, punit->y)) + if (is_military_unit(punit)) return TRUE; return FALSE; } @@ -547,6 +547,7 @@ case ACTIVITY_FORTIFIED: text = _("Fortified"); break; case ACTIVITY_FORTRESS: text = _("Fortress"); break; case ACTIVITY_SENTRY: text = _("Sentry"); break; + case ACTIVITY_AUTO_ATTACK: text = _("Autoattack"); break; case ACTIVITY_RAILROAD: text = _("Railroad"); break; case ACTIVITY_PILLAGE: text = _("Pillage"); break; case ACTIVITY_GOTO: text = _("Goto"); break; @@ -650,6 +651,9 @@ case ACTIVITY_PATROL: return TRUE; + case ACTIVITY_AUTO_ATTACK: + return is_military_unit(punit); + case ACTIVITY_POLLUTION: return unit_flag(punit, F_SETTLERS) && tile_has_special(ptile, S_POLLUTION); @@ -922,6 +926,7 @@ case ACTIVITY_AIRBASE: case ACTIVITY_FORTRESS: case ACTIVITY_SENTRY: + case ACTIVITY_AUTO_ATTACK: case ACTIVITY_GOTO: case ACTIVITY_EXPLORE: case ACTIVITY_PATROL: Index: common/unit.h =================================================================== RCS file: /home/freeciv/CVS/freeciv/common/unit.h,v retrieving revision 1.90 diff -u -r1.90 unit.h --- common/unit.h 2002/11/15 21:24:30 1.90 +++ common/unit.h 2002/11/18 19:36:33 @@ -26,7 +26,7 @@ ACTIVITY_IRRIGATE, ACTIVITY_FORTIFIED, ACTIVITY_FORTRESS, ACTIVITY_SENTRY, ACTIVITY_RAILROAD, ACTIVITY_PILLAGE, ACTIVITY_GOTO, ACTIVITY_EXPLORE, ACTIVITY_TRANSFORM, ACTIVITY_UNKNOWN, ACTIVITY_AIRBASE, ACTIVITY_FORTIFYING, - ACTIVITY_FALLOUT, ACTIVITY_PATROL, + ACTIVITY_FALLOUT, ACTIVITY_PATROL, ACTIVITY_AUTO_ATTACK, ACTIVITY_LAST /* leave this one last */ }; Index: server/autoattack.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/server/autoattack.c,v retrieving revision 1.40 diff -u -r1.40 autoattack.c --- server/autoattack.c 2002/09/30 13:08:56 1.40 +++ server/autoattack.c 2002/11/18 19:36:34 @@ -191,6 +191,62 @@ } /************************************************************************** +Attacking unit in adjacent tile. +**************************************************************************/ +static bool do_auto_attack_unit(struct unit *pattacker, struct unit *pdefender) +{ + freelog(LOG_DEBUG, "launching attack"); + if (handle_unit_move_request(pattacker, pdefender->x, pdefender->y, FALSE, FALSE)){ + return TRUE; + } else { + return FALSE; + } +} + +/************************************************************************** +This is only useful if attacked unit isn't on a adjacent tile. +Isn't working correct ... +**************************************************************************/ +static void do_goto_auto_attack_unit(struct unit *pattacker, struct unit *pdefender) +{ + int id = pattacker->id; + int attacker_x, attacker_y; + freelog(LOG_DEBUG, "launching attack"); + + notify_player_ex(unit_owner(pattacker), pdefender->x, pdefender->y, E_NOEVENT, + _("Game: Auto-Attack: %s attacking %s's %s"), + unit_name(pattacker->type), unit_owner(pdefender)->name, + unit_name(pdefender->type)); + + attacker_x = pattacker->x; + attacker_y = pattacker->y; + + set_unit_activity(pattacker, ACTIVITY_GOTO); + pattacker->goto_dest_x=pdefender->x; + pattacker->goto_dest_y=pdefender->y; + + send_unit_info(NULL, pattacker); + (void) do_unit_goto(pattacker, GOTO_MOVE_ANY, FALSE); + + pattacker = find_unit_by_id(id); + + if (pattacker) { + set_unit_activity(pdefender, ACTIVITY_GOTO); + pattacker->goto_dest_x=attacker_x; + pattacker->goto_dest_y=attacker_y; + send_unit_info(NULL, pattacker); + + (void) do_unit_goto(pattacker, GOTO_MOVE_ANY, FALSE); + + if (unit_list_find(&map_get_tile(attacker_x, attacker_y)->units, id)) { + handle_unit_activity_request(pattacker, ACTIVITY_AUTO_ATTACK); + } + send_unit_info(NULL, pattacker); + } + return; +} + +/************************************************************************** ... **************************************************************************/ static void auto_attack_city(struct player *pplayer, struct city *pcity) @@ -257,3 +313,78 @@ 1000.0*read_timer_seconds(t)); } } + +/************************************************************************** +This is called when a enemy unit is moving into the range of a unit with +the AUTO_ATTACK Flag. +**************************************************************************/ +void enemy_unit_auto_attack(struct unit *pautoattacker, struct unit *pmover) +{ + int chance_to_win, value_autoattacker, value_defending_unit; + int attackpower, defensepower, attack_firepower, defense_firepower; + int magic_number = 1; + int auto_attack_value; + struct unit *defender; + + /* perhaps can_unit_attack_unit_at_tile is more correct */ + if (can_unit_attack_tile(pautoattacker, pmover->x, pmover->y)){ + + defender = get_defender(pautoattacker, pmover->x, pmover->y); + freelog(LOG_DEBUG, "defender is %s", unit_name(defender->type)); + + /* from unit_versus_unit */ + attackpower = get_total_attack_power(pautoattacker,defender); + defensepower = get_total_defense_power(pautoattacker,defender); + get_modified_firepower(pautoattacker, defender, + &attack_firepower, &defense_firepower); + + chance_to_win = (attackpower * attack_firepower * pautoattacker->hp * 100) / + ((defensepower * defense_firepower * defender->hp) + + (attackpower * attack_firepower * pautoattacker->hp)); + freelog(LOG_DEBUG, "chance to win is %d", chance_to_win); + + value_autoattacker = unit_value(pautoattacker->type); + if (pautoattacker->veteran) value_autoattacker=(value_autoattacker*3)/2; + + value_defending_unit = unit_value(pmover->type); + /* here should be some modifications for stacks ... */ + + auto_attack_value = (value_autoattacker * 100 / + (value_defending_unit + value_autoattacker)); + + freelog(LOG_DEBUG, "auto_attack_value=%d",auto_attack_value); + + /* when do we want to attack? */ + /* tried it with the distance code ... more errors than benefit */ + + if (chance_to_win >= 50 && + chance_to_win >= (auto_attack_value * magic_number)){ + (void) do_auto_attack_unit(pautoattacker, defender); + +/* this is the code for attacking tiles farer away .. its not that easy to get it to work, so we attack adjacent tiles only */ + /* + if (!do_auto_attack_unit(pautoattacker, defender)){ + int mv_cost, range; +*/ + /* if a 'F_ONEATTACK' unit, + range is larger, because they are not going to return this turn anyways + *//* + range = unit_flag(pautoattacker, F_ONEATTACK) ? + pautoattacker->moves_left : + pautoattacker->moves_left/2; + *//* attack the next to this place */ + /* range = range<4 ? 3 : range; + + + mv_cost = calculate_move_cost(pautoattacker, defender->x, defender->y); + freelog(LOG_DEBUG, "move_cost is %d",mv_cost); + if (mv_cost > range+3) { + freelog(LOG_DEBUG, "too far away: %d", mv_cost); + } + do_goto_auto_attack_unit(pautoattacker, defender); + } +*/ + } + } +} + Index: server/autoattack.h =================================================================== RCS file: /home/freeciv/CVS/freeciv/server/autoattack.h,v retrieving revision 1.2 diff -u -r1.2 autoattack.h --- server/autoattack.h 1999/07/11 12:57:57 1.2 +++ server/autoattack.h 2002/11/18 19:36:34 @@ -14,5 +14,6 @@ #define FC__AUTOATTACK_H void auto_attack(void); +void enemy_unit_auto_attack(struct unit *pautoattacker, struct unit *pmover); #endif /* FC__AUTOATTACK_H */ Index: server/unittools.c =================================================================== RCS file: /home/freeciv/CVS/freeciv/server/unittools.c,v retrieving revision 1.196 diff -u -r1.196 unittools.c --- server/unittools.c 2002/11/18 12:19:51 1.196 +++ server/unittools.c 2002/11/18 19:36:35 @@ -2840,6 +2840,34 @@ } } unit_list_iterate_end; } square_iterate_end; + + /* Wakeup the units which are setted to auto_attack and let them + * attack + * */ + square_iterate(punit->x, punit->y, 1, x, y) { + unit_list_iterate(map_get_tile(x, y)->units, penemy) { + int range; + enum unit_move_type move_type = unit_type(penemy)->move_type; + enum tile_terrain_type terrain = map_get_terrain(x, y); + + if (map_has_special(x, y, S_FORTRESS) + && unit_profits_of_watchtower(penemy)) + range = get_watchtower_vision(penemy); + else + range = unit_type(penemy)->vision_range; + + if (!pplayers_allied(unit_owner(punit), unit_owner(penemy)) + && penemy->activity == ACTIVITY_AUTO_ATTACK + && map_get_known_and_seen(punit->x, punit->y, unit_owner(penemy)) + && range >= real_map_distance(punit->x, punit->y, x, y) + && player_can_see_unit(unit_owner(penemy), punit) + /* on board transport; don't awaken */ + && !(move_type == LAND_MOVING && terrain == T_OCEAN)) { + send_unit_info(NULL, penemy); + enemy_unit_auto_attack(penemy, punit); + } + } unit_list_iterate_end; + } square_iterate_end; } /**************************************************************************