TbBool setup_person_move_close_to_position(struct Thing *thing, MapSubtlCoord stl_x, MapSubtlCoord stl_y, NaviRouteFlags flags) { struct CreatureControl *cctrl; struct Coord3d trgpos; struct Coord3d navpos; SYNCDBG(18,"Moving %s index %d to (%d,%d)",thing_model_name(thing),(int)thing->index,(int)stl_x,(int)stl_y); trgpos.x.val = subtile_coord_center(stl_x); trgpos.y.val = subtile_coord_center(stl_y); trgpos.z.val = thing->mappos.z.val; cctrl = creature_control_get_from_thing(thing); if (creature_control_invalid(cctrl)) { WARNLOG("Tried to move invalid creature to (%d,%d)",(int)stl_x,(int)stl_y); return false; } get_nearest_navigable_point_for_thing(thing, &trgpos, &navpos, flags); if (!creature_can_navigate_to_with_storage(thing, &navpos, flags)) { SYNCDBG(19,"The %s cannot reach subtile (%d,%d)",thing_model_name(thing),(int)stl_x,(int)stl_y); return false; } cctrl->move_flags = flags; internal_set_thing_state(thing, CrSt_MoveToPosition); cctrl->moveto_pos.x.val = navpos.x.val; cctrl->moveto_pos.y.val = navpos.y.val; cctrl->moveto_pos.z.val = navpos.z.val; return true; }
TbBool setup_person_move_to_position_f(struct Thing *thing, MapSubtlCoord stl_x, MapSubtlCoord stl_y, NaviRouteFlags flags, const char *func_name) { struct CreatureControl *cctrl; struct Coord3d locpos; SYNCDBG(18,"%s: Moving %s index %d to (%d,%d)",func_name,thing_model_name(thing),(int)thing->index,(int)stl_x,(int)stl_y); TRACE_THING(thing); locpos.x.val = subtile_coord_center(stl_x); locpos.y.val = subtile_coord_center(stl_y); locpos.z.val = thing->mappos.z.val; locpos.z.val = get_thing_height_at(thing, &locpos); cctrl = creature_control_get_from_thing(thing); if (creature_control_invalid(cctrl)) { WARNLOG("%s: Tried to move invalid creature to (%d,%d)",func_name,(int)stl_x,(int)stl_y); return false; } if (thing_in_wall_at(thing, &locpos)) { SYNCDBG(16,"%s: The %s would be trapped in wall at (%d,%d)",func_name,thing_model_name(thing),(int)stl_x,(int)stl_y); return false; } if (!creature_can_navigate_to_with_storage_f(thing, &locpos, flags, func_name)) { SYNCDBG(19,"%s: The %s cannot reach subtile (%d,%d)",func_name,thing_model_name(thing),(int)stl_x,(int)stl_y); return false; } cctrl->move_flags = flags; internal_set_thing_state(thing, CrSt_MoveToPosition); cctrl->moveto_pos.x.val = locpos.x.val; cctrl->moveto_pos.y.val = locpos.y.val; cctrl->moveto_pos.z.val = locpos.z.val; SYNCDBG(19,"%s: Done",func_name); return true; }
struct Thing *get_trap_for_slab_position(MapSlabCoord slb_x, MapSlabCoord slb_y) { MapCoord pos_x,pos_y; pos_x = subtile_coord_center(slab_subtile_center(slb_x)); pos_y = subtile_coord_center(slab_subtile_center(slb_y)); return get_trap_around_of_model_and_owned_by(pos_x, pos_y, -1, -1); }
struct Thing *create_crate_in_workshop(struct Room *room, ThingModel cratngmodel, MapSubtlCoord stl_x, MapSubtlCoord stl_y) { struct Coord3d pos; struct Thing *cratetng; if (!room_role_matches(room->kind, RoRoF_CratesStorage)) { SYNCDBG(4,"Crate %s cannot be created in a %s owned by player %d, wrong room",object_code_name(cratngmodel),room_code_name(room->kind),(int)room->owner); return INVALID_THING; } pos.x.val = subtile_coord_center(stl_x); pos.y.val = subtile_coord_center(stl_y); pos.z.val = 0; cratetng = create_object(&pos, cratngmodel, room->owner, -1); if (thing_is_invalid(cratetng)) { return INVALID_THING; } // Neutral thing do not need any more processing if (is_neutral_thing(cratetng) || !player_exists(get_player(room->owner))) { return cratetng; } if (!add_workshop_object_to_workshop(room, cratetng)) { ERRORLOG("Could not fit %s in %s index %d", thing_model_name(cratetng),room_code_name(room->kind),(int)room->index); //remove_item_from_room_capacity(room); -- no need, it was not added destroy_object(cratetng); return INVALID_THING; } ThingClass tngclass; ThingModel tngmodel; tngclass = crate_thing_to_workshop_item_class(cratetng); tngmodel = crate_thing_to_workshop_item_model(cratetng); add_workshop_item_to_amounts(cratetng->owner, tngclass, tngmodel); return cratetng; }
long instf_destroy(struct Thing *creatng, long *param) { struct Dungeon *dungeon; struct Room *room; struct SlabMap *slb; MapSlabCoord slb_x,slb_y; long prev_owner; TRACE_THING(creatng); slb_x = subtile_slab_fast(creatng->mappos.x.stl.num); slb_y = subtile_slab_fast(creatng->mappos.y.stl.num); dungeon = get_dungeon(creatng->owner); slb = get_slabmap_block(slb_x, slb_y); room = room_get(slb->room_index); prev_owner = slabmap_owner(slb); if ( !room_is_invalid(room) && (prev_owner != creatng->owner) ) { if (room->health > 1) { room->health--; return 0; } clear_dig_on_room_slabs(room, creatng->owner); if (room->owner == game.neutral_player_num) { claim_room(room, creatng); } else { MapCoord ccor_x,ccor_y; ccor_x = subtile_coord_center(room->central_stl_x); ccor_y = subtile_coord_center(room->central_stl_y); event_create_event_or_update_nearby_existing_event(ccor_x, ccor_y, EvKind_RoomLost, room->owner, 0); claim_enemy_room(room, creatng); } thing_play_sample(creatng, 76, NORMAL_PITCH, 0, 3, 0, 2, FULL_LOUDNESS); create_effects_on_room_slabs(room, imp_spangle_effects[creatng->owner], 0, creatng->owner); return 0; } if (slb->health > 1) { slb->health--; return 0; } if (prev_owner != game.neutral_player_num) { struct Dungeon *prev_dungeon; prev_dungeon = get_dungeon(prev_owner); prev_dungeon->lvstats.territory_lost++; } decrease_dungeon_area(prev_owner, 1); neutralise_enemy_block(creatng->mappos.x.stl.num, creatng->mappos.y.stl.num, creatng->owner); remove_traps_around_subtile(slab_subtile_center(slb_x), slab_subtile_center(slb_y), NULL); switch_owned_objects_on_destoyed_slab_to_neutral(slb_x, slb_y, prev_owner); dungeon->lvstats.territory_destroyed++; return 1; }
short good_attack_room(struct Thing *thing) { // Debug code to find incorrect states if (!is_hero_thing(thing)) { ERRORLOG("Non hero %s index %d owner %d - reset",thing_model_name(thing),(int)thing->index,(int)thing->owner); set_start_state(thing); return 0; } //return _DK_good_attack_room(thing); MapSlabCoord base_slb_x,base_slb_y; base_slb_x = subtile_slab_fast(thing->mappos.x.stl.num); base_slb_y = subtile_slab_fast(thing->mappos.y.stl.num); struct Room *room; room = slab_room_get(base_slb_x, base_slb_y); // If the current tile can be destroyed if (room_exists(room) && (room->owner != thing->owner) && !room_cannot_vandalise(room->kind)) { struct CreatureControl *cctrl; cctrl = creature_control_get_from_thing(thing); if (cctrl->instance_id == CrInst_NULL) { set_creature_instance(thing, CrInst_ATTACK_ROOM_SLAB, 1, 0, 0); MapCoord ev_coord_x,ev_coord_y; ev_coord_x = subtile_coord_center(room->central_stl_x); ev_coord_y = subtile_coord_center(room->central_stl_y); event_create_event_or_update_nearby_existing_event(ev_coord_x, ev_coord_y, EvKind_RoomUnderAttack, room->owner, 0); if (is_my_player_number(room->owner)) output_message(SMsg_EnemyDestroyRooms, MESSAGE_DELAY_FIGHT, true); } return 1; } // Otherwise, search around for a tile to destroy long m,n; m = ACTION_RANDOM(SMALL_AROUND_SLAB_LENGTH); for (n=0; n < SMALL_AROUND_SLAB_LENGTH; n++) { MapSlabCoord slb_x,slb_y; slb_x = base_slb_x + (long)small_around[m].delta_x; slb_y = base_slb_y + (long)small_around[m].delta_y; room = slab_room_get(slb_x, slb_y); if (room_exists(room) && (room->owner != thing->owner)) { if (setup_person_move_to_position(thing, slb_x, slb_y, NavRtF_Default)) { thing->continue_state = CrSt_GoodAttackRoom1; return 1; } } m = (m+1) % SMALL_AROUND_SLAB_LENGTH; } set_start_state(thing); return 0; }
long computer_check_neutral_places(struct Computer2 *comp, struct ComputerCheck * check) { SYNCDBG(8,"Starting"); //return _DK_computer_check_neutral_places(comp, check); struct Comp2_UnkStr1 *rel; rel = &comp->unkarr_A10[game.neutral_player_num]; struct Room *near_room; struct Coord3d *near_pos; int near_dist; near_room = INVALID_ROOM; near_dist = 2147483647; near_pos = &rel->pos_A[0]; int i; for (i=0; i < 64; i++) { struct Coord3d *place; place = &rel->pos_A[i]; if ((place->x.val == 0) || (place->y.val == 0)) { continue; } struct Room *room; room = INVALID_ROOM; if (computer_finds_nearest_room_to_pos(comp, &room, place)) { MapSubtlDelta dx,dy; dx = abs((int)room->central_stl_x - (MapSubtlDelta)place->x.stl.num); dy = abs((int)room->central_stl_y - (MapSubtlDelta)place->y.stl.num); if (near_dist > dx+dy) { near_room = room; near_pos = place; near_dist = dx+dy; } } } if (room_is_invalid(near_room)) { return 4; } struct Coord3d endpos; struct Coord3d startpos; endpos.x.val = near_pos->x.val; endpos.y.val = near_pos->y.val; endpos.z.val = near_pos->z.val; startpos.x.val = subtile_coord_center(stl_slab_center_subtile(near_room->central_stl_x)); startpos.y.val = subtile_coord_center(stl_slab_center_subtile(near_room->central_stl_y)); startpos.z.val = subtile_coord(1,0); if (!create_task_dig_to_neutral(comp, startpos, endpos)) { return 4; } near_pos->x.val = 0; near_pos->y.val = 0; near_pos->z.val = 0; return 1; }
short setup_person_tunnel_to_position(struct Thing *creatng, MapSubtlCoord stl_x, MapSubtlCoord stl_y, unsigned char a4) { struct CreatureControl *cctrl; if ( internal_set_thing_state(creatng, CrSt_Tunnelling) ) { cctrl = creature_control_get_from_thing(creatng); cctrl->moveto_pos.x.val = subtile_coord_center(stl_x); cctrl->moveto_pos.y.val = subtile_coord_center(stl_y); cctrl->moveto_pos.z.val = get_thing_height_at(creatng, &cctrl->moveto_pos); } return 0; }
void find_nearest_rooms_for_ambient_sound(void) { struct PlayerInfo *player; struct Room *room; struct MapOffset *sstep; struct Coord3d pos; long slb_x,slb_y; MapSubtlCoord stl_x,stl_y; long i,k; SYNCDBG(8,"Starting"); if ((SoundDisabled) || (GetCurrentSoundMasterVolume() <= 0)) return; player = get_my_player(); struct Camera *cam; cam = player->acamera; if (cam == NULL) { ERRORLOG("No active camera"); set_room_playing_ambient_sound(NULL, 0); return; } slb_x = subtile_slab(cam->mappos.x.stl.num); slb_y = subtile_slab(cam->mappos.y.stl.num); for (i = 0; i < 11*11; i++) { sstep = &spiral_step[i]; stl_x = slab_subtile_center(slb_x + sstep->h); stl_y = slab_subtile_center(slb_y + sstep->v); if (subtile_is_player_room(player->id_number,stl_x,stl_y)) { room = subtile_room_get(stl_x, stl_y); if (room_is_invalid(room)) continue; struct RoomConfigStats *roomst; roomst = &slab_conf.room_cfgstats[room->kind]; k = roomst->ambient_snd_smp_id; if (k > 0) { SYNCDBG(8,"Playing ambient for %s at (%d,%d)",room_code_name(room->kind),(int)stl_x,(int)stl_y); pos.x.val = subtile_coord_center(stl_x); pos.y.val = subtile_coord_center(stl_y); pos.z.val = subtile_coord(1,0); set_room_playing_ambient_sound(&pos, k); return; } } } set_room_playing_ambient_sound(NULL, 0); }
void setup_training_move(struct Thing *creatng, SubtlCodedCoords stl_num) { struct CreatureControl *cctrl; cctrl = creature_control_get_from_thing(creatng); cctrl->moveto_pos.x.val = subtile_coord_center(stl_num_decode_x(stl_num)); cctrl->moveto_pos.y.val = subtile_coord_center(stl_num_decode_y(stl_num)); cctrl->moveto_pos.z.val = get_thing_height_at(creatng, &cctrl->moveto_pos); if (thing_in_wall_at(creatng, &cctrl->moveto_pos)) { ERRORLOG("Illegal setup to wall at (%d,%d)", (int)cctrl->moveto_pos.x.stl.num, (int)cctrl->moveto_pos.y.stl.num); set_start_state(creatng); } SYNCDBG(18,"The %s is moving to (%d,%d)", thing_model_name(creatng), (int)cctrl->moveto_pos.x.stl.num, (int)cctrl->moveto_pos.y.stl.num); }
short good_arrived_at_attack_room(struct Thing *thing) { struct Room *room; room = get_room_thing_is_on(thing); // If the current tile can be destroyed if (room_exists(room) && (room->owner != thing->owner) && !room_cannot_vandalise(room->kind)) { internal_set_thing_state(thing, CrSt_GoodAttackRoom1); MapCoord ev_coord_x,ev_coord_y; ev_coord_x = subtile_coord_center(room->central_stl_x); ev_coord_y = subtile_coord_center(room->central_stl_y); event_create_event_or_update_nearby_existing_event(ev_coord_x, ev_coord_y, EvKind_RoomUnderAttack, room->owner, 0); if (is_my_player_number(room->owner)) output_message(SMsg_EnemyDestroyRooms, MESSAGE_DELAY_FIGHT, true); return 1; } set_start_state(thing); return 0; }
void init_dungeon_essential_position(struct Dungeon *dungeon) { struct Room *room; room = room_get(dungeon->room_kind[RoK_DUNGHEART]); RoomKind rkind; for (rkind = 1; rkind < ROOM_TYPES_COUNT; rkind++) { if (!room_is_invalid(room)) break; room = room_get(dungeon->room_kind[rkind]); } if (room_is_invalid(room)) { dungeon->essential_pos.x.val = subtile_coord_center(map_subtiles_x/2); dungeon->essential_pos.y.val = subtile_coord_center(map_subtiles_y/2); dungeon->essential_pos.z.val = subtile_coord(0,1); return; } dungeon->essential_pos.x.val = subtile_coord_center(room->central_stl_x); dungeon->essential_pos.y.val = subtile_coord_center(room->central_stl_y); dungeon->essential_pos.z.val = subtile_coord(0,1); }
/** * Quick attack is just putting CTA spell on enemy room. * @param comp * @param check */ long computer_check_for_quick_attack(struct Computer2 *comp, struct ComputerCheck * check) { struct Dungeon *dungeon; SYNCDBG(8,"Starting"); //return _DK_computer_check_for_quick_attack(comp, check); dungeon = comp->dungeon; int creatrs_num; creatrs_num = check->param1 * dungeon->num_active_creatrs / 100; if (check->param3 >= creatrs_num) { return 4; } if (computer_able_to_use_magic(comp, PwrK_CALL2ARMS, 1, 3) != 1) { return 4; } if ((check_call_to_arms(comp) != 1) || is_there_an_attack_task(comp)) { return 4; } struct Room *room; room = get_hated_room_for_quick_attack(comp, check->param3); if (room_is_invalid(room)) { return 4; } struct Coord3d pos; // TODO COMPUTER_PLAYER We should make sure the place of cast is accessible for creatures pos.x.val = subtile_coord_center(room->central_stl_x); pos.y.val = subtile_coord_center(room->central_stl_y); pos.z.val = subtile_coord(1,0); if (check->param3 >= count_creatures_availiable_for_fight(comp, &pos)) { return 4; } if (!create_task_magic_support_call_to_arms(comp, &pos, check->param2, 0, creatrs_num)) { return 4; } output_message(SMsg_EnemyHarassments+ACTION_RANDOM(8), 500, 1); return 1; }
void process_creature_in_training_room(struct Thing *thing, struct Room *room) { static const struct Around corners[] = { {1, 2}, {0, 1}, {1, 0}, {2, 1}, }; struct CreatureControl *cctrl; struct CreatureStats *crstat; struct Thing *traintng; struct Thing *crtng; struct CreatureControl *cctrl2; struct Coord3d pos; long speed,dist; long i; cctrl = creature_control_get_from_thing(thing); SYNCDBG(8,"Starting %s mode %d",thing_model_name(thing),(int)cctrl->training.mode); //_DK_process_creature_in_training_room(thing, room); return; cctrl->field_4A = 0; switch (cctrl->training.mode) { case CrTrMd_SearchForTrainPost: // While we're in an instance, just wait if (cctrl->instance_id != CrInst_NULL) break; // On timeout, search for nearby training posts to start training ASAP if (cctrl->training.search_timeout < 1) { SYNCDBG(6,"Search timeout - selecting post nearest to (%d,%d)",(int)thing->mappos.x.stl.num, (int)thing->mappos.y.stl.num); setup_training_search_for_post(thing); cctrl->training.search_timeout = 100; break; } // Do a moving step cctrl->training.search_timeout--; speed = get_creature_speed(thing); i = creature_move_to(thing, &cctrl->moveto_pos, speed, 0, 0); if (i == 1) { // Move target is reached - find a training post which is supposed to be around here traintng = find_training_post_just_next_to_creature(thing); if (thing_is_invalid(traintng)) { SYNCDBG(6,"Reached (%d,%d) but there's no training post there",(int)thing->mappos.x.stl.num, (int)thing->mappos.y.stl.num); setup_move_to_new_training_position(thing, room, false); break; } // Found - go to next mode cctrl->training.mode = CrTrMd_SelectPositionNearTrainPost; cctrl->training.search_timeout = 50; } else if (i == -1) { ERRORLOG("Cannot get to (%d,%d) in the training room",(int)cctrl->moveto_pos.x.stl.num,(int)cctrl->moveto_pos.y.stl.num); set_start_state(thing); } break; case CrTrMd_SelectPositionNearTrainPost: for (i=0; i < 4; i++) { long slb_x,slb_y; long stl_x,stl_y; struct SlabMap *slb; slb_x = subtile_slab_fast(thing->mappos.x.stl.num) + (long)small_around[i].delta_x; slb_y = subtile_slab_fast(thing->mappos.y.stl.num) + (long)small_around[i].delta_y; slb = get_slabmap_block(slb_x,slb_y); if ((slb->kind != SlbT_TRAINING) || (slabmap_owner(slb) != thing->owner)) continue; stl_x = slab_subtile(slb_x,corners[i].delta_x); stl_y = slab_subtile(slb_y,corners[i].delta_y); traintng = INVALID_THING; // Check if any other creature is using that post; allow only unused posts crtng = get_creature_of_model_training_at_subtile_and_owned_by(stl_x, stl_y, -1, thing->owner, thing->index); if (thing_is_invalid(crtng)) { traintng = get_object_at_subtile_of_model_and_owned_by(slab_subtile_center(slb_x), slab_subtile_center(slb_y), 31, thing->owner); } if (!thing_is_invalid(traintng)) { cctrl->training.pole_stl_x = slab_subtile_center(subtile_slab_fast(thing->mappos.x.stl.num)); cctrl->training.pole_stl_y = slab_subtile_center(subtile_slab_fast(thing->mappos.y.stl.num)); cctrl->moveto_pos.x.stl.num = stl_x; cctrl->moveto_pos.y.stl.num = stl_y; cctrl->moveto_pos.x.stl.pos = 128; cctrl->moveto_pos.y.stl.pos = 128; cctrl->moveto_pos.z.val = get_thing_height_at(thing, &cctrl->moveto_pos); if (thing_in_wall_at(thing, &cctrl->moveto_pos)) { ERRORLOG("Illegal setup to (%d,%d)", (int)cctrl->moveto_pos.x.stl.num, (int)cctrl->moveto_pos.y.stl.num); break; } cctrl->training.mode = CrTrMd_MoveToTrainPost; break; } } if (cctrl->training.mode == CrTrMd_SelectPositionNearTrainPost) setup_move_to_new_training_position(thing, room, 1); break; case CrTrMd_MoveToTrainPost: speed = get_creature_speed(thing); i = creature_move_to(thing, &cctrl->moveto_pos, speed, 0, 0); if (i == 1) { // If there's already someone training at that position, go somewhere else crtng = get_creature_of_model_training_at_subtile_and_owned_by(thing->mappos.x.stl.num, thing->mappos.y.stl.num, -1, thing->owner, thing->index); if (!thing_is_invalid(crtng)) { setup_move_to_new_training_position(thing, room, 1); break; } // Otherwise, train at this position cctrl->training.mode = CrTrMd_TurnToTrainPost; } else if (i == -1) { ERRORLOG("Cannot get where we're going in the training room."); set_start_state(thing); } break; case CrTrMd_TurnToTrainPost: pos.x.val = subtile_coord_center(cctrl->training.pole_stl_x); pos.y.val = subtile_coord_center(cctrl->training.pole_stl_y); if (creature_turn_to_face(thing, &pos) < 56) { cctrl->training.mode = CrTrMd_DoTrainWithTrainPost; cctrl->training.train_timeout = 75; } break; case CrTrMd_PartnerTraining: if (cctrl->training.partner_idx == 0) { setup_move_to_new_training_position(thing, room, false); return; } crtng = thing_get(cctrl->training.partner_idx); TRACE_THING(crtng); if (!thing_exists(crtng) || (get_creature_state_besides_move(crtng) != CrSt_Training) || (crtng->creation_turn != cctrl->training.partner_creation)) { SYNCDBG(8,"The %s cannot start partner training - creature to train with is gone.",thing_model_name(thing)); setup_move_to_new_training_position(thing, room, false); return; } cctrl2 = creature_control_get_from_thing(crtng); if (cctrl2->training.partner_idx != thing->index) { SYNCDBG(6,"The %s cannot start partner training - %s changed the partner.",thing_model_name(thing),thing_model_name(crtng)); cctrl->training.partner_idx = 0; setup_move_to_new_training_position(thing, room, false); break; } if (get_room_thing_is_on(crtng) != room) { SYNCDBG(8,"The %s cannot start partner training - partner has left the room.",thing_model_name(thing)); cctrl->training.partner_idx = 0; cctrl2->training.partner_idx = 0; setup_move_to_new_training_position(thing, room, false); break; } crstat = creature_stats_get_from_thing(thing); dist = get_combat_distance(thing, crtng); if (dist > 284) { if (creature_move_to(thing, &crtng->mappos, get_creature_speed(thing), 0, 0) == -1) { WARNLOG("The %s cannot navigate to training partner",thing_model_name(thing)); setup_move_to_new_training_position(thing, room, false); cctrl->training.partner_idx = 0; } } else if (dist >= 156) { if (creature_turn_to_face(thing, &crtng->mappos) < 56) { cctrl->training.train_timeout--; if (cctrl->training.train_timeout > 0) { if ((cctrl->instance_id == CrInst_NULL) && ((cctrl->training.train_timeout % 8) == 0)) { set_creature_instance(thing, CrInst_SWING_WEAPON_SWORD, 1, 0, 0); } } else { if (cctrl->instance_id == CrInst_NULL) { setup_move_to_new_training_position(thing, room, false); cctrl->training.partner_idx = 0; } else { cctrl->training.train_timeout = 1; } cctrl->exp_points += (room->efficiency * crstat->training_value); } } } else { creature_retreat_from_combat(thing, crtng, 33, 0); } break; case CrTrMd_DoTrainWithTrainPost: if (cctrl->training.train_timeout > 0) { // While training timeout is positive, continue initiating the train instances cctrl->training.train_timeout--; if ((cctrl->instance_id == CrInst_NULL) && ((cctrl->training.train_timeout % 8) == 0)) { set_creature_instance(thing, CrInst_SWING_WEAPON_SWORD, 1, 0, 0); } } else { // Wait for the instance to end, then select new move position if (cctrl->instance_id != CrInst_NULL) { cctrl->training.train_timeout = 0; } else { cctrl->training.train_timeout = 0; setup_move_to_new_training_position(thing, room, true); } } break; default: WARNLOG("Invalid %s training mode %d; reset",thing_model_name(thing),(int)cctrl->training.mode); cctrl->training.mode = CrTrMd_SearchForTrainPost; cctrl->training.search_timeout = 0; break; } SYNCDBG(18,"End"); }
long instf_dig(struct Thing *creatng, long *param) { struct CreatureControl *cctrl; struct Dungeon *dungeon; struct SlabMap *slb; long stl_x,stl_y; long task_idx,taskkind; long dig_damage,gold; SYNCDBG(16,"Starting"); TRACE_THING(creatng); //return _DK_instf_dig(thing, param); cctrl = creature_control_get_from_thing(creatng); dungeon = get_dungeon(creatng->owner); task_idx = cctrl->word_91; { struct MapTask *task; task = get_dungeon_task_list_entry(dungeon,task_idx); taskkind = task->kind; if (task->coords != cctrl->word_8F) { return 0; } stl_x = stl_num_decode_x(cctrl->word_8F); stl_y = stl_num_decode_y(cctrl->word_8F); } slb = get_slabmap_for_subtile(stl_x, stl_y); if (slabmap_block_invalid(slb)) { return 0; } dig_damage = calculate_damage_did_to_slab_with_single_hit(creatng, slb); if (slb->health > dig_damage) { if (!slab_kind_is_indestructible(slb->kind)) slb->health -= dig_damage; thing_play_sample(creatng, 63 + UNSYNC_RANDOM(6), NORMAL_PITCH, 0, 3, 0, 2, FULL_LOUDNESS); create_effect(&creatng->mappos, TngEff_Unknown25, creatng->owner); if (taskkind == SDDigTask_MineGold) { gold = calculate_gold_digged_out_of_slab_with_single_hit(dig_damage, creatng->owner, cctrl->explevel, slb); creatng->creature.gold_carried += gold; dungeon->lvstats.gold_mined += gold; } return 0; } // slb->health <= dig_damage - we're going to destroy the slab remove_from_task_list(creatng->owner, task_idx); if (taskkind == SDDigTask_MineGold) { gold = calculate_gold_digged_out_of_slab_with_single_hit(slb->health, creatng->owner, cctrl->explevel, slb); creatng->creature.gold_carried += gold; dungeon->lvstats.gold_mined += gold; mine_out_block(stl_x, stl_y, creatng->owner); if (dig_has_revealed_area(stl_x, stl_y, creatng->owner)) { EventIndex evidx; evidx = event_create_event_or_update_nearby_existing_event( subtile_coord_center(stl_x), subtile_coord_center(stl_y), EvKind_AreaDiscovered, creatng->owner, 0); if ((evidx > 0) && is_my_player_number(creatng->owner)) output_message(SMsg_DugIntoNewArea, 0, true); } } else if (taskkind == SDDigTask_DigEarth) { dig_out_block(stl_x, stl_y, creatng->owner); if (dig_has_revealed_area(stl_x, stl_y, creatng->owner)) { EventIndex evidx; evidx = event_create_event_or_update_nearby_existing_event( subtile_coord_center(stl_x), subtile_coord_center(stl_y), EvKind_AreaDiscovered, creatng->owner, 0); if ((evidx > 0) && is_my_player_number(creatng->owner)) output_message(SMsg_DugIntoNewArea, 0, true); } } check_map_explored(creatng, stl_x, stl_y); thing_play_sample(creatng, 72 + UNSYNC_RANDOM(3), NORMAL_PITCH, 0, 3, 0, 4, FULL_LOUDNESS); return 1; }
TbBool find_place_to_put_door_around_room(const struct Room *room, struct Coord3d *pos) { long m,n; m = ACTION_RANDOM(SMALL_AROUND_SLAB_LENGTH); for (n = 0; n < SMALL_AROUND_SLAB_LENGTH; n++) { // Get position containing room center MapSlabCoord slb_x,slb_y; slb_x = subtile_slab_fast(room->central_stl_x); slb_y = subtile_slab_fast(room->central_stl_y); // Move the position to edge of the room struct Room *sibroom; sibroom = slab_room_get(slb_x, slb_y); while (!room_is_invalid(sibroom) && (sibroom->index == room->index)) { slb_x += small_around[m].delta_x; slb_y += small_around[m].delta_y; sibroom = slab_room_get(slb_x, slb_y); } // Move the position a few tiles further in that direction searching for a place to put door //TODO COMPUTER_PLAYER Why we can only have doors if corridor is at center of the room? This should be fixed to allow doors everywhere around room. int i; for (i = 4; i > 0; i--) { struct SlabMap *slb; slb = get_slabmap_block(slb_x, slb_y); if ((slabmap_owner(slb) != room->owner) || (slb->kind != SlbT_CLAIMED)) { i = 0; break; } if (tag_cursor_blocks_place_door(room->owner, slab_subtile_center(slb_x), slab_subtile_center(slb_y))) { break; } if (!subtile_has_door_thing_on(slab_subtile_center(slb_x), slab_subtile_center(slb_y))) { // No door - the position looks ok break; } slb_x += small_around[m].delta_x; slb_y += small_around[m].delta_y; } // Now if we were able to move, then the position seem ok. One last check - make sure the corridor is not dead end and doesn't already have a door if (i > 0) { MapSlabCoord nxslb_x,nxslb_y; nxslb_x = slb_x + small_around[m].delta_x; nxslb_y = slb_y + small_around[m].delta_y; struct SlabMap *nxslb; nxslb = get_slabmap_block(nxslb_x, nxslb_y); if ((slabmap_owner(nxslb) == room->owner) && (nxslb->kind == SlbT_CLAIMED)) { if (!subtile_has_door_thing_on(slab_subtile_center(nxslb_x), slab_subtile_center(nxslb_y))) { pos->x.val = subtile_coord_center(slab_subtile_center(slb_x)); pos->y.val = subtile_coord_center(slab_subtile_center(slb_y)); pos->z.val = subtile_coord(1,0); return true; } } } m = (m + 1) % SMALL_AROUND_SLAB_LENGTH; } return false; }
long process_creature_in_workshop(struct Thing *creatng, struct Room *room) { //return _DK_process_creature_in_workshop(creatng, room); struct CreatureControl *cctrl; cctrl = creature_control_get_from_thing(creatng); struct Dungeon *dungeon; dungeon = get_dungeon(creatng->owner); if ((game.play_gameturn - dungeon->field_118B < 50) && ((game.play_gameturn + creatng->index) & 3) == 0) { if (cctrl->instance_id == CrInst_NULL) { set_creature_instance(creatng, CrInst_CELEBRATE_SHORT, 1, 0, 0); } return 1; } if (cctrl->instance_id != CrInst_NULL) { return 1; } long mvret; MapSlabCoord slb_x, slb_y; SYNCDBG(19,"Work in %s, the %s in state %d",room_code_name(room->kind),thing_model_name(creatng),(int)cctrl->byte_9A); switch (cctrl->byte_9A) { case 1: cctrl->byte_9E--; if (cctrl->byte_9E <= 0) { setup_workshop_search_for_post(creatng); cctrl->byte_9E = 100; break; } mvret = creature_move_to(creatng, &cctrl->moveto_pos, get_creature_speed(creatng), 0, 0); if (mvret != 1) { if (mvret == -1) { SYNCDBG(9,"Room %s move problem, the %s goes from %d to start state",room_code_name(room->kind),thing_model_name(creatng),(int)cctrl->byte_9A); set_start_state(creatng); } break; } slb_x = subtile_slab_fast(creatng->mappos.x.stl.num); slb_y = subtile_slab_fast(creatng->mappos.y.stl.num); struct Thing *objtng; objtng = get_workshop_equipment_to_work_with_on_subtile(creatng->owner, slab_subtile_center(slb_x),slab_subtile_center(slb_y)); if (!thing_is_invalid(objtng)) { SYNCDBG(19,"Got %s post, the %s goes from %d to 2",room_code_name(room->kind),thing_model_name(creatng),(int)cctrl->byte_9A); cctrl->byte_9A = 2; cctrl->byte_9E = 100; break; } SYNCDBG(19,"No %s post at current pos, the %s goes from %d to search position",room_code_name(room->kind),thing_model_name(creatng),(int)cctrl->byte_9A); setup_move_to_new_workshop_position(creatng, room, 0); break; case 2: { SubtlCodedCoords stl_num; stl_num = find_unused_adjacent_position_in_workshop(&creatng->mappos, creatng->owner); if (stl_num != 0) { slb_x = subtile_slab_fast(stl_num_decode_x(stl_num)); slb_y = subtile_slab_fast(stl_num_decode_y(stl_num)); cctrl->byte_9C = slab_subtile_center(slb_x); cctrl->byte_9D = slab_subtile_center(slb_y); setup_workshop_move(creatng, stl_num); cctrl->byte_9A = 3; break; } SYNCDBG(9,"No free adjacent %s post, the %s goes from %d to search position",room_code_name(room->kind),thing_model_name(creatng),(int)cctrl->byte_9A); setup_move_to_new_workshop_position(creatng, room, 1); break; } case 3: { mvret = creature_move_to(creatng, &cctrl->moveto_pos, get_creature_speed(creatng), 0, 0); if (mvret != 1) { if (mvret == -1) { SYNCDBG(9,"Room %s move problem, the %s goes from %d to start state",room_code_name(room->kind),thing_model_name(creatng),(int)cctrl->byte_9A); set_start_state(creatng); } break; } struct Thing *mnfc_creatng; mnfc_creatng = get_other_creature_manufacturing_on_subtile(creatng->owner, creatng->mappos.x.stl.num, creatng->mappos.y.stl.num, creatng); if (thing_is_invalid(mnfc_creatng)) { cctrl->byte_9A = 4; break; } // Position used by another manufacturer SYNCDBG(9,"The %s post already in use, the %s goes from %d to search position",room_code_name(room->kind),thing_model_name(creatng),(int)cctrl->byte_9A); setup_move_to_new_workshop_position(creatng, room, 1); break; } case 4: { struct Coord3d pos; pos.x.val = subtile_coord_center(cctrl->byte_9C); pos.y.val = subtile_coord_center(cctrl->byte_9D); if (creature_turn_to_face(creatng, &pos) < 56) { cctrl->byte_9A = 5; cctrl->byte_9B = 75; } break; } case 5: default: cctrl->byte_9B--; if (cctrl->byte_9B <= 0) { SYNCDBG(9,"Room %s move counter %d, the %s keeps moving in state %d",room_code_name(room->kind),(int)cctrl->byte_9B,thing_model_name(creatng),(int)cctrl->byte_9A); setup_move_to_new_workshop_position(creatng, room, 1); } else if ((cctrl->byte_9B % 8) == 0) { set_creature_instance(creatng, CrInst_SWING_WEAPON_SWORD, 1, 0, 0); } break; } return 1; }
long computer_check_neutral_places(struct Computer2 *comp, struct ComputerCheck * check) { if (is_newdig_enabled(comp)) return 4; SYNCDBG(8,"Starting"); struct Dungeon *dungeon; dungeon = comp->dungeon; if (dungeon_invalid(dungeon) || !player_has_heart(dungeon->owner)) { SYNCDBG(7,"Computer players %d dungeon in invalid or has no heart",(int)dungeon->owner); return CTaskRet_Unk4; } struct OpponentRelation *oprel; oprel = &comp->opponent_relations[game.neutral_player_num]; struct Room *near_room; struct Coord3d *near_pos; int near_dist; near_room = INVALID_ROOM; near_dist = LONG_MAX; near_pos = &oprel->pos_A[0]; int i; for (i=0; i < COMPUTER_SPARK_POSITIONS_COUNT; i++) { struct Coord3d *place; place = &oprel->pos_A[i]; if ((place->x.val == 0) || (place->y.val == 0)) { continue; } struct Room *room; room = INVALID_ROOM; if (computer_finds_nearest_room_to_pos(comp, &room, place)) { MapSubtlDelta dx,dy; dx = abs((int)room->central_stl_x - (MapSubtlDelta)place->x.stl.num); dy = abs((int)room->central_stl_y - (MapSubtlDelta)place->y.stl.num); if (near_dist > dx+dy) { near_room = room; near_pos = place; near_dist = dx+dy; } } } if (room_is_invalid(near_room)) { return CTaskRet_Unk4; } struct Coord3d endpos; struct Coord3d startpos; endpos.x.val = near_pos->x.val; endpos.y.val = near_pos->y.val; endpos.z.val = near_pos->z.val; startpos.x.val = subtile_coord_center(stl_slab_center_subtile(near_room->central_stl_x)); startpos.y.val = subtile_coord_center(stl_slab_center_subtile(near_room->central_stl_y)); startpos.z.val = subtile_coord(1,0); if (!create_task_dig_to_neutral(comp, startpos, endpos)) { return CTaskRet_Unk4; } near_pos->x.val = 0; near_pos->y.val = 0; near_pos->z.val = 0; return CTaskRet_Unk1; }