short move_to_position(struct Thing *creatng) { CreatureStateCheck callback; struct CreatureControl *cctrl; struct StateInfo *stati; long move_result; CrCheckRet state_check; long speed; TRACE_THING(creatng); cctrl = creature_control_get_from_thing(creatng); speed = get_creature_speed(creatng); SYNCDBG(18,"Starting to move %s index %d into (%d,%d)",thing_model_name(creatng),(int)creatng->index,(int)cctrl->moveto_pos.x.stl.num,(int)cctrl->moveto_pos.y.stl.num); // Try teleporting the creature if (creature_move_to_using_teleport(creatng, &cctrl->moveto_pos, speed)) { SYNCDBG(8,"Teleporting %s index %d owner %d into (%d,%d) for %s",thing_model_name(creatng),(int)creatng->index,(int)creatng->owner, (int)cctrl->moveto_pos.x.stl.num,(int)cctrl->moveto_pos.y.stl.num,creature_state_code_name(creatng->continue_state)); return 1; } move_result = creature_move_to(creatng, &cctrl->moveto_pos, speed, cctrl->move_flags, 0); state_check = CrCkRet_Available; stati = get_thing_continue_state_info(creatng); if (!state_info_invalid(stati)) { callback = stati->move_check; if (callback != NULL) { SYNCDBG(18,"Doing move check callback for continue state %s",creature_state_code_name(creatng->continue_state)); state_check = callback(creatng); } } if (state_check == CrCkRet_Available) { // If moving was successful if (move_result == 1) { // Back to "main state" internal_set_thing_state(creatng, creatng->continue_state); return CrStRet_Modified; } // If moving failed, do a reset if (move_result == -1) { CrtrStateId cntstat; cntstat = creatng->continue_state; internal_set_thing_state(creatng, cntstat); set_start_state(creatng); SYNCDBG(8,"Couldn't move %s to place required for state %s; reset to state %s",thing_model_name(creatng),creature_state_code_name(cntstat),creatrtng_actstate_name(creatng)); return CrStRet_ResetOk; } // If continuing the job, check for job stress process_job_stress_and_going_postal(creatng); } switch (state_check) { case CrCkRet_Deleted: return CrStRet_Deleted; case CrCkRet_Available: return CrStRet_Modified; default: return CrStRet_ResetOk; } }
CrStateRet guarding(struct Thing *thing) { struct Room *room; TRACE_THING(thing); room = get_room_thing_is_on(thing); if (creature_job_in_room_no_longer_possible(room, Job_GUARD, thing)) { remove_creature_from_work_room(thing); set_start_state(thing); return CrStRet_ResetFail; } struct CreatureControl *cctrl; cctrl = creature_control_get_from_thing(thing); if (creature_move_to(thing, &cctrl->moveto_pos, cctrl->max_speed, 0, 0) == 0) { return CrStRet_Unchanged; } if (!person_get_somewhere_adjacent_in_room(thing, room, &cctrl->moveto_pos)) { cctrl->moveto_pos.x.val = thing->mappos.x.val; cctrl->moveto_pos.y.val = thing->mappos.y.val; cctrl->moveto_pos.z.val = thing->mappos.z.val; } return CrStRet_Modified; }
short creature_freeze_prisonors(struct Thing *creatng) { struct CreatureControl *cctrl; cctrl = creature_control_get_from_thing(creatng); if (cctrl->instance_id != CrInst_NULL) { return 1; } if (!creature_instance_has_reset(creatng, CrInst_FREEZE)) { if (creature_choose_random_destination_on_valid_adjacent_slab(creatng)) { creatng->continue_state = CrSt_CreatureFreezePrisoners; } return 1; } struct Thing *victng; victng = find_prisoner_for_thing(creatng); if (thing_is_invalid(victng)) { set_start_state(creatng); return 0; } long dist; dist = get_combat_distance(creatng, victng); if (dist < 156) { creature_retreat_from_combat(creatng, victng, CrSt_CreatureFreezePrisoners, 0); } else if ((dist <= 2048) && (creature_can_see_combat_path(creatng, victng, dist) > AttckT_Unset)) { set_creature_instance(creatng, CrInst_FREEZE, 1, victng->index, 0); } else { creature_move_to(creatng, &victng->mappos, cctrl->max_speed, 0, 0); } 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 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; }