void move() { if (status->objects[0].long_attack_casting==0) longattack_target=-1; if (longattack_target!=-1) { int enemy=enemy_id(longattack_target); if (map->objects[enemy].shield_time>=status->objects[0].long_attack_casting); Position pos=map->objects[enemy].pos; if (Distance(pos,status->objects[0].pos)>=kLongAttackRange[status->objects[0].skill_level[LONG_ATTACK]]-kMaxMoveSpeed*2) { Position speed; speed.x=-100*(status->objects[0].pos.x-pos.x); speed.y=-100*(status->objects[0].pos.y-pos.y); speed.z=-100*(status->objects[0].pos.z-pos.z); Move(status->objects[0].id,speed); return; }; }; int danger=danger_move(); if (danger!=-1) { Position speed; speed.x=100*(status->objects[0].pos.x-map->objects[danger].pos.x); speed.y=100*(status->objects[0].pos.y-map->objects[danger].pos.y); speed.z=100*(status->objects[0].pos.z-map->objects[danger].pos.z); Move(status->objects[0].id,speed); return; }; int enemy=find_enemy(); if (enemy!=-1) { Position speed; speed.x=-100*(status->objects[0].pos.x-map->objects[enemy].pos.x); speed.y=-100*(status->objects[0].pos.y-map->objects[enemy].pos.y); speed.z=-100*(status->objects[0].pos.z-map->objects[enemy].pos.z); Move(status->objects[0].id,speed); return; }; int ENERGY=find_ENERGY(); if (ENERGY!=-1) { Position speed; speed.x=-100*(status->objects[0].pos.x-map->objects[ENERGY].pos.x); speed.y=-100*(status->objects[0].pos.y-map->objects[ENERGY].pos.y); speed.z=-100*(status->objects[0].pos.z-map->objects[ENERGY].pos.z); Move(status->objects[0].id,speed); return; }; Position speed; speed.x=-100*(status->objects[0].pos.x-(kMapSize>>1)); speed.y=-100*(status->objects[0].pos.y-(kMapSize>>1)); speed.z=-100*(status->objects[0].pos.z-(kMapSize>>1)); Move(status->objects[0].id,speed); return; };
void move() { int danger = danger_move(); if (danger != -1) { Position speed; speed.x = 100 * (status->objects[0].pos.x - map->objects[danger].pos.x); speed.y = 100 * (status->objects[0].pos.y - map->objects[danger].pos.y); speed.z = 100 * (status->objects[0].pos.z - map->objects[danger].pos.z); Move(status->objects[0].id, speed); return; }; int enemy = find_enemy(); if (enemy != -1) { Position speed; speed.x = -100 * (status->objects[0].pos.x - map->objects[enemy].pos.x); speed.y = -100 * (status->objects[0].pos.y - map->objects[enemy].pos.y); speed.z = -100 * (status->objects[0].pos.z - map->objects[enemy].pos.z); Move(status->objects[0].id, speed); return; }; int ENERGY = find_ENERGY(); if (ENERGY != -1) { Position speed; speed.x = -100 * (status->objects[0].pos.x - map->objects[ENERGY].pos.x); speed.y = -100 * (status->objects[0].pos.y - map->objects[ENERGY].pos.y); speed.z = -100 * (status->objects[0].pos.z - map->objects[ENERGY].pos.z); Move(status->objects[0].id, speed); return; }; Position speed; speed.x = -100 * (status->objects[0].pos.x - (kMapSize >> 1)); speed.y = -100 * (status->objects[0].pos.y - (kMapSize >> 1)); speed.z = -100 * (status->objects[0].pos.z - (kMapSize >> 1)); Move(status->objects[0].id, speed); return; };
void play_loop(t_share *shared, t_player *player) { usleep(TIME); lock(); if (shared->kill == TRUE) { if (shared->nb_team == 1) { unlock(); shared->end = TRUE; } } if (check_if_dead(shared, player) == -1) { shared->kill = TRUE; unlock(); return ; } find_enemy(shared, player); move(shared, player); unlock(); }
bool melee(mob_t * attacker, int speed) { char line[DEFLEN]; mob_t * target; int att_x; int range; int i; range = attacker->range; att_x = attacker->x; if (speed > 0) att_x++; for (i = 0; i < range; i++) { att_x += speed; target = find_enemy(attacker, player->y, att_x); if (target == NULL) continue; if (target->type == MOB_MIMIC && target->attack_phase == 0) { pwait("WAIT! THAT IS A SMALL MIMIC!"); target->attack_phase = 1; target->flags = 0; return true; } else if (target->type == MOB_BLURK && target->attack_phase == 0) { draw_board_norefresh(); pwait("OH NO! AN INSIDIOUS BLURK BARS YOUR WAY!"); target->attack_phase = 1; target->flags = 0; return true; } // Attack! // The attacker must always lower their shield attacker->shd_up = 0; if (attacker == player && game->weapon > WPN_UNARMED) { damage_weapon(1); } // If the target has their shield up and they are facing each other if (target->shd_up && target->flip != attacker->flip) { if (shield_block(target)) { mob_text(target, "BLOCK"); damage_shield(target); if (target->type == MOB_KNAVE) { if (target->attack_phase == 0) target->attack_phase = 1; else if (target->attack_phase == 1 || target->attack_phase == 2) { move_towards_player(target); } } return true; } } damage(attacker, target); if (attacker->attack_frames == 2) { attacker->flags = GFX_ATTACK2; draw_board(); lpause(); attacker->flags = 0; } attacker->flags = GFX_ATTACK; draw_board(); lpause(); attacker->flags = 0; damage_armor(target); // Draining dagger restores attacker HP if (attacker == player && game->weapon == WPN_DRAIN) { attacker->hp += 1; } if (target->hp > 0) { // Keep track of who we are fighting if (attacker == player) { enemy_bar = target->index; enemy_bar_time = BAR_TIMEOUT; draw_bars(); } else if (target == player) { enemy_bar = attacker->index; enemy_bar_time = BAR_TIMEOUT; draw_bars(); } } target->flags = GFX_HURT; draw_board(); lpause(); target->flags = 0; if (target->hp <= 0) { if (target == player) { snprintf(line, DEFLEN, "YOU WERE %s\n" "BY %s%s", attacker->killverb, article[attacker->article], mob_name[attacker->type]); draw_bars(); game_over(line, false); } else { kill_enemy(target); } } if (attacker->type == MOB_ROGUE && game->player_gold > ROGUE_STEAL_GOLD && rand() % 100 < ROGUE_STEAL_CHANCE) { rogue_escape(attacker); } return true; } return false; }
int shoot_missile(mob_t * attacker, int dir) { char line[DEFLEN]; mob_t * target; int m_y; int m_x; int sc_y; int sc_x; int count; int m_type; int adjust_y; int passes; int pass; int xbow; chtype color; chtype missile; // attacker = &game->mob[mi]; xbow = false; passes = 1; adjust_y = water_offset(attacker); m_y = attacker->y; sc_y = m_y - view_y - 1; m_x = attacker->x + (attacker->flip ? -attacker->pack_w + 2 : attacker->pack_w - 2) + dir * 2; if (attacker->type == MOB_EYE) { m_type = MIS_DISINT; sc_y -= 1; m_x = attacker->x; } else if (attacker->type == MOB_LICH) { m_type = MIS_FIREBALL; sc_y -= 1; } else if (attacker == player) { if (game->weapon == WPN_BOW) m_type = MIS_ARROW; else if (game->weapon == WPN_3XBOW) { xbow = true; m_type = MIS_ARROW; if (water_offset(attacker)) passes = 2; else passes = 3; } else if (game->weapon == WPN_BLASTER) { m_type = MIS_BLASTER; adjust_y -= 1; } } else { m_type = MIS_ARROW; } draw_board(); for (pass = 0; pass < passes; pass++) { count = 0; if (xbow) { m_x = attacker->x + (attacker->flip ? -attacker->pack_w + 2 : attacker->pack_w - 2) + dir * 2; if (pass == 0) adjust_y = water_offset(attacker) - 1; else if (pass == 1) adjust_y = water_offset(attacker); else if (pass == 2) adjust_y = water_offset(attacker) + 1; } while (1) { m_x += dir; sc_x = m_x - view_x; count++; if (sc_x < 0 || sc_x >= BOARD_W) goto end_pass;//break;//return 0; target = find_enemy(attacker, m_y, m_x + dir); if (target == NULL) { if (game->blinded) continue; if (m_type != MIS_BLASTER && count % 2 == 1) continue; // Skip the length of the barrel if (m_type == MIS_BLASTER && count < 4) continue; missile = '?'; color = COLOR_PAIR(PAIR_GREEN); if (m_type == MIS_ARROW) { missile = '-'; color = COLOR_PAIR(PAIR_MAGENTA); } if (m_type == MIS_BLASTER) { missile = '='; color = COLOR_PAIR(PAIR_MAGENTA); } else if (m_type == MIS_FIREBALL) { missile = '*'; color = COLOR_PAIR(PAIR_RED); } else if (m_type == MIS_DISINT) { missile = (dir > 0 ? '>' : '<'); color = COLOR_PAIR(PAIR_RED); } if (water_join(gtile(m_y - 1, m_x))) { color = COLOR_PAIR(PAIR_BLACK_ON_CYAN); } if (m_type == MIS_BLASTER) { mvwaddch(board, sc_y + adjust_y, sc_x, '_' | color); /* if (count % 2) mvwaddch(board, sc_y, sc_x, (dir > 0 ? ')' : '(') | color); else mvwaddch(board, sc_y - 1, sc_x, (dir > 0 ? ')' : '(') | color);*/ } else mvwaddch(board, sc_y + adjust_y, sc_x, missile | color); wrefresh(board); spause(); continue; } if (target->shd_up && ((!target->flip && dir < 0) || (target->flip && dir > 0)) ) { if (target == player && m_type == MIS_DISINT && target->shd_type != SHD_NONE && target->shd_type != SHD_MAGIC) { flush_input(); snprintf(line, DEFLEN, "DISINTEGRATION BEAM!!\n\nYOUR %s\nCRUMBLES TO DUST!", armor_name[target->shd_type]); pwait(line); target->shd_type = SHD_NONE; target->shd_up = false; goto end_pass;//return true; } if (m_type != MIS_BLASTER && shield_block(target)) { mob_text(target, "BLOCK"); damage_shield(target); goto end_pass; //return true; } } if (target == player && m_type == MIS_DISINT) { if (target->armor_type != ARMOR_NONE && target->armor_type != ARMOR_MAGIC) { flush_input(); snprintf(line, DEFLEN, "DISINTEGRATION BEAM!!\n\nYOUR %s\nCRUMBLES TO DUST!", armor_name[target->armor_type]); pwait(line); target->armor_type = ARMOR_NONE; goto end_pass;// return true; } if (game->weapon != WPN_UNARMED) { flush_input(); snprintf(line, DEFLEN, "DISINTEGRATION BEAM!!\n\nYOUR %s\nCRUMBLES TO DUST!", weapon_name[game->weapon]); pwait(line); give_weapon(WPN_UNARMED); goto end_pass; //return true; } } damage(attacker, target); if (m_type == MIS_ARROW) { target->flags = GFX_HURT; draw_board(); lpause(); target->flags = 0; } else if (m_type == MIS_BLASTER) { target->flags = GFX_HURT; draw_board(); lpause(); target->flags = 0; } else if (m_type == MIS_FIREBALL) { explosion(sc_y, sc_x + dir); } if (target == player) { draw_bars(); } if (target->hp <= 0) { if (target == player) { snprintf(line, DEFLEN, "YOU WERE %s\n" "BY %s%s", (m_type == MIS_FIREBALL ? "FRIED" : (m_type == MIS_DISINT ? "DISINTEGRATED" : "SHOT")), article[attacker->article], mob_name[attacker->type]); draw_board(); game_over(line, false); } else { if (!xbow || pass == passes - 1) kill_enemy(target); goto end_pass; } } else if (target != player) { enemy_bar = target->index; enemy_bar_time = BAR_TIMEOUT; draw_bars(); // update the number of eyes it has if (target->type == MOB_BIGSPIDER) draw_board();// draw_board(); } damage_armor(target); goto end_pass; } end_pass: continue; } // return 1; // } return 1; }
// ------------------------------------------------------------------------ // window to display an adventure map // ------------------------------------------------------------------------ void t_adventure_map_window::check_enemy_attack( t_army* army, t_handler enemy_attack_started_handler ) { if (m_attacking_enemy != 0) return; if (army->empty() || army->is_graveyard()) return; t_adventure_path_finder* frame_path_finder; t_owned_ptr<t_adventure_path_finder> local_finder; t_adventure_path_finder* path_finder; t_adv_map_point point; point = army->get_position(); frame_path_finder = m_frame->get_path_finder(); if (frame_path_finder->get_army() == army) path_finder = frame_path_finder; else { local_finder.reset( new t_adventure_path_finder( *m_map )); path_finder = local_finder.get(); path_finder->set_army( army ); } if ( !path_finder->get_data( point ).actual_enemy_adjacent ) return; // find adjacent army t_direction direction; t_army* enemy; enemy = find_enemy( *m_map, *path_finder, point, *army, &direction ); assert( enemy != 0 ); if (enemy == 0) return; t_level_map_point_2d enemy_position = enemy->get_position(); if ((abs( enemy_position.row - point.row ) > 1 || abs(enemy_position.column - point.column ) > 1) && enemy->ai_value() * 5.0 <= army->ai_value()) { if (attempt_retreat( enemy, direction, this )) return; } // suppress activation if the enemy is hidden, except for neutrals if (enemy->get_owner_number() >= 0) { int team; if (army->get_owner_number() < 0) team = -1; else team = army->get_owner()->get_team(); if (!enemy->is_visible_to( team )) return; } // move enemy to attack t_adventure_path path; local_finder.reset( new t_adventure_path_finder( *m_map )); path_finder = local_finder.get(); path_finder->set_army( enemy ); path_finder->set_path_type( k_path_search_enemy_activation ); if (!path_finder->get_path( army->get_position(), path )) return; // Allow caller to close windows and the like before combat actually starts enemy_attack_started_handler(); t_counted_ptr<t_army_mover> mover; t_window_ptr ref = this; m_attacking_enemy = enemy; enemy->set_path( path ); m_map->clear_path(); m_map->clear_selection(); enemy->set_in_combat( true ); // make visible regardless of stealth as it attacks. run_object_mover( new t_enemy_army_attack( this, enemy, army ), false ); }
// ------------------------------------------------------------------------ // Initialize from local or derived constructor. If use_army_path is false, // m_path must already be set up. // ------------------------------------------------------------------------ void t_army_mover::initialize( t_adventure_map_window* window, t_army* army, bool limit_move, t_adventure_path_finder const* path_finder, bool use_army_path ) { m_window = window; m_army = army; m_in_trigger = false; m_exceeded_move_limit = false; m_is_visible = false; m_movement_expended = 0; m_has_trigger = false; m_landing = false; m_limit_move = limit_move; m_original_position = army->get_position(); t_adventure_map& map = *army->get_map(); if ( use_army_path ) { t_adventure_path path = army->get_path(); int i; int move_left = army->get_movement(); bool is_boat = army->is_boat(); bool enemy_enforced_dest = false; t_creature_array const* restricting_enemy = NULL; t_adv_map_point restricted_dest; t_player* owner = army->get_owner(); bool is_computer = owner && owner->is_computer(); bool built_boat = false; bool hidden_enemy = false; // copy path until we run out of movement or encounter a trigger for (i = path.size() - 1; i >= 0; i--) { t_adventure_path_point& point = path[i]; // If the path goes into the attack radius of a hidden enemy // then truncate the path if ( path_finder != 0 && point.actual_enemy_adjacent && point.actual_enemy_distance > 0 && ( !point.visible_enemy_adjacent || point.actual_enemy_direction != point.visible_enemy_direction || point.actual_enemy_distance != point.visible_enemy_distance )) { restricting_enemy = find_enemy( map, *path_finder, point, *m_army ); if (restricting_enemy != 0) { int stealth_advantage; stealth_advantage = restricting_enemy->get_stealth_level() - m_army->get_anti_stealth_level(); if (stealth_advantage <= 0) break; if (stealth_advantage == 1 || restricting_enemy->get_owner_number() < 0) hidden_enemy = true; } } if ( path_finder && ( point.visible_restricts_movement || enemy_enforced_dest ) ) { if (enemy_enforced_dest) { if ( (point != restricted_dest) && (point != restricting_enemy->get_position()) ) break; } else { restricting_enemy = find_restrictive_enemy( map, *path_finder, point, *m_army ); if (restricting_enemy != NULL) enemy_enforced_dest = true; } restricted_dest = point + get_direction_offset( point.actual_enemy_direction ); } if (point.move_cost > move_left && limit_move) { m_actual_destination = point.last_point; m_exceeded_move_limit = true; break; } if (map.get_trigger_object( point.last_point, point.direction, army )) { m_has_trigger = true; m_trigger_point = point; } if (is_boat) { if (!map.is_ocean( point )) { m_landing = true; m_trigger_point = point; break; } } else if (is_computer && !m_has_trigger && map.is_ocean( point ) && !m_exceeded_move_limit) { t_adventure_tile const& last_tile = map[point]; t_hero* most_spell_points = NULL; if ( map.has_empty_boat( *m_army->get_owner() ) ) { int most_spell_points_count = 0; for (int i = 0; i < t_creature_array::k_size; i++) { t_hero* hero = (*m_army)[i].get_hero(); if (hero && hero->can_cast( k_spell_summon_boat )) { int cur_spell_points = hero->get_spell_points(); if ( (most_spell_points == NULL) || ( cur_spell_points > most_spell_points_count ) ) { most_spell_points = hero; most_spell_points_count = cur_spell_points; } } } } if (most_spell_points != NULL) { army->get_adventure_frame()->ai_cast_summon_boat( *m_army, *most_spell_points, point ); } else if (last_tile.ai_can_build_ship()) { t_adventure_object& object = map.get_adv_object(last_tile.ai_get_shipyard_id()); t_adv_shipyard* shipyard = dynamic_cast< t_adv_shipyard* >( &object ); t_adv_map_point boat_position; if (shipyard != NULL) built_boat = shipyard->find_new_ship_position( boat_position ); else { t_town* town = object.get_town(); if (town) { if ( !town->has( k_town_shipyard) ) { if (town->has_built()) break; town->buy_building( k_town_shipyard ); } built_boat = town->find_new_ship_position( boat_position, false ); } } if (built_boat) { t_army* boat = new t_army( army->get_creatures().get_leader().get_alignment() ); boat->set_owner( army->get_owner_number() ); boat->place( map, boat_position ); owner->spend( army->get_ai()->get_boat_cost() ); // This destination pick wouldn't have been // made unless he already had the cash. } } } if (map[point].blocks_army( *army, map, point.on_bridge, k_path_search_move_army )) break; // if the path actually enters a cell of an enemy, stop. if (point.actual_enemy_adjacent && point.actual_enemy_distance == 0) break; m_path.push_back( point ); if (m_has_trigger || built_boat || hidden_enemy) break; } } m_halted = false; m_step = -1; m_distance = compute_overall_distance( m_path, 0 ); if (m_path.size() == 0) { m_cell_distance = 0; m_crossing_point = -1; m_distance = 0; m_frames = 0; m_divisor = 1; m_delta = t_screen_point(0,0); m_offset = t_screen_point(0,0); m_distance_delta = 0; m_is_visible = !m_army->hidden_by_fog_of_war( map.get_player().get_team() ); } else { m_army->set_action( k_adv_actor_action_prewalk ); start_new_square(); prepare_move( 0 ); } set_next_time( get_time() ); }