short creature_drop_body_in_prison(struct Thing *thing) { struct CreatureControl *cctrl; cctrl = creature_control_get_from_thing(thing); struct Thing *dragtng; dragtng = thing_get(cctrl->dragtng_idx); if (!thing_exists(dragtng) || !creature_is_being_unconscious(dragtng)) { set_start_state(thing); return 0; } if (!subtile_is_room(thing->mappos.x.stl.num, thing->mappos.y.stl.num)) { set_start_state(thing); return 0; } struct Room *room; room = get_room_thing_is_on(thing); if ((room->owner != thing->owner) || (room->kind != RoK_PRISON)) { set_start_state(thing); return 0; } make_creature_conscious(dragtng); initialise_thing_state(dragtng, CrSt_CreatureArrivedAtPrison); struct CreatureControl *dragctrl; dragctrl = creature_control_get_from_thing(dragtng); dragctrl->flgfield_1 |= CCFlg_NoCompControl; set_start_state(thing); return 1; }
short at_guard_post_room(struct Thing *thing) { struct CreatureControl *cctrl; struct Room *room; cctrl = creature_control_get_from_thing(thing); cctrl->target_room_id = 0; room = get_room_thing_is_on(thing); if (!room_initially_valid_as_type_for_thing(room, get_room_for_job(Job_GUARD), thing)) { WARNLOG("Room %s owned by player %d is invalid for %s index %d",room_code_name(room->kind),(int)room->owner,thing_model_name(thing),(int)thing->index); set_start_state(thing); return 0; } if (!add_creature_to_work_room(thing, room, Job_GUARD)) { set_start_state(thing); return 0; } internal_set_thing_state(thing, get_continue_state_for_job(Job_GUARD)); 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 1; }
/** * Does a step of being imprisoned. * Informs if the imprisoning cycle should end. * @param thing */ CrCheckRet process_prison_function(struct Thing *creatng) { struct Room *room; room = get_room_creature_works_in(creatng); if (!room_still_valid_as_type_for_thing(room, RoK_PRISON, creatng)) { WARNLOG("Room %s owned by player %d is bad work place for %s index %d owner %d",room_code_name(room->kind),(int)room->owner,thing_model_name(creatng),(int)creatng->index,(int)creatng->owner); set_start_state(creatng); return CrCkRet_Continue; } process_creature_hunger(creatng); if ( process_prisoner_skelification(creatng,room) ) return CrCkRet_Deleted; struct CreatureControl *cctrl; cctrl = creature_control_get_from_thing(creatng); if ((cctrl->instance_id == CrInst_NULL) && process_prison_food(creatng, room) ) return CrCkRet_Continue; // Breaking from jail is only possible once per some amount of turns if ((game.play_gameturn % gameadd.time_between_prison_break) == 0) { if (jailbreak_possible(room, creatng->owner)) { if (is_my_player_number(room->owner)) output_message(SMsg_PrisonersEscaping, 40, true); else if (is_my_player_number(room->owner)) output_message(SMsg_CreatrFreedPrison, 40, true); set_start_state(creatng); return CrCkRet_Continue; } } return CrCkRet_Available; }
short creature_hero_entering(struct Thing *thing) { struct CreatureControl *cctrl; TRACE_THING(thing); //return _DK_creature_hero_entering(thing); cctrl = creature_control_get_from_thing(thing); if (cctrl->field_282 > 0) { cctrl->field_282--; return CrStRet_Unchanged; } if (cctrl->field_282 == 0) { thing->mappos.z.val = get_ceiling_height(&thing->mappos) - (long)thing->field_58 - 1; cctrl->field_282--; return CrStRet_Modified; } if ( thing_touching_floor(thing) || (((thing->movement_flags & TMvF_Flying) != 0) && thing_touching_flight_altitude(thing))) { set_start_state(thing); return CrStRet_ResetOk; } if (cctrl->field_282 < -500) { set_start_state(thing); return CrStRet_ResetFail; } cctrl->field_282--; return CrStRet_Modified; }
CrStateRet creature_at_changed_lair(struct Thing *creatng) { struct Room *room; TRACE_THING(creatng); //return _DK_creature_at_changed_lair(thing); if (!thing_is_on_own_room_tile(creatng)) { set_start_state(creatng); return CrStRet_ResetFail; } room = get_room_thing_is_on(creatng); if (!room_initially_valid_as_type_for_thing(room, RoK_LAIR, creatng)) { WARNLOG("Room %s owned by player %d is invalid for %s",room_code_name(room->kind),(int)room->owner,thing_model_name(creatng)); set_start_state(creatng); return CrStRet_ResetFail; } if (!creature_add_lair_to_room(creatng, room)) { internal_set_thing_state(creatng, CrSt_CreatureChooseRoomForLairSite); return CrStRet_Modified; } // All done - finish the state set_start_state(creatng); return CrStRet_ResetOk; }
CrCheckRet process_scavenge_function(struct Thing *calltng) { SYNCDBG(18,"Starting for %s owner %d",thing_model_name(calltng),(int)calltng->owner); //return _DK_process_scavenge_function(thing); struct CreatureControl *callctrl; callctrl = creature_control_get_from_thing(calltng); struct Dungeon *calldngn; struct Room *room; calldngn = get_dungeon(calltng->owner); room = get_room_creature_works_in(calltng); if ( !room_still_valid_as_type_for_thing(room, RoK_SCAVENGER, calltng) ) { WARNLOG("Room %s owned by player %d is bad work place for %s owned by played %d",room_code_name(room->kind),(int)room->owner,thing_model_name(calltng),(int)calltng->owner); set_start_state(calltng); return CrCkRet_Continue; } struct CreatureStats *crstat; crstat = creature_stats_get_from_thing(calltng); if (!player_can_afford_to_scavenge_creature(calltng)) { if (is_my_player_number(calltng->owner)) output_message(SMsg_NoGoldToScavenge, 500, 1); set_start_state(calltng); return CrCkRet_Continue; } if (calldngn->scavenge_counters_turn != game.play_gameturn) { reset_scavenge_counts(calldngn); } long work_value; work_value = compute_creature_work_value(crstat->scavenge_value*256, room->efficiency, callctrl->explevel); work_value = process_work_speed_on_work_value(calltng, work_value); SYNCDBG(9,"The %s index %d owner %d produced %d scavenge points",thing_model_name(calltng),(int)calltng->index,(int)calltng->owner,(int)work_value); struct Thing *scavtng; scavtng = get_scavenger_target(calltng); if (!thing_is_invalid(scavtng)) { process_scavenge_creature_from_level(scavtng, calltng, work_value); } else if (can_scavenge_creature_from_pool(calldngn, calltng->model)) { process_scavenge_creature_from_pool(calltng, work_value); } else { if (crstat->entrance_force) { calldngn->field_1485++; } return 0; } callctrl->field_82++; if (callctrl->field_82 > game.scavenge_cost_frequency) { callctrl->field_82 -= game.scavenge_cost_frequency; if (take_money_from_dungeon(calltng->owner, crstat->scavenger_cost, 1) < 0) { ERRORLOG("Cannot take %d gold from dungeon %d",(int)crstat->scavenger_cost,(int)calltng->owner); } create_price_effect(&calltng->mappos, calltng->owner, crstat->scavenger_cost); } return 0; }
short at_scavenger_room(struct Thing *thing) { struct CreatureControl *cctrl; struct CreatureStats *crstat; struct Dungeon *dungeon; struct Room *room; //return _DK_at_scavenger_room(thing); room = get_room_thing_is_on(thing); if (!room_initially_valid_as_type_for_thing(room, RoK_SCAVENGER, thing)) { WARNLOG("Room %s owned by player %d is invalid for %s index %d",room_code_name(room->kind),(int)room->owner,thing_model_name(thing),(int)thing->index); set_start_state(thing); return 0; } cctrl = creature_control_get_from_thing(thing); crstat = creature_stats_get_from_thing(thing); dungeon = get_dungeon(thing->owner); if (crstat->scavenger_cost >= dungeon->total_money_owned) { if (is_my_player_number(thing->owner)) output_message(SMsg_NoGoldToScavenge, MESSAGE_DELAY_TREASURY, true); set_start_state(thing); return 0; } if (!add_creature_to_work_room(thing, room)) { set_start_state(thing); return 0; } internal_set_thing_state(thing, CrSt_Scavengering); cctrl->field_82 = 0; return 1; }
CrStateRet creature_in_prison(struct Thing *thing) { struct Room *room; TRACE_THING(thing); room = get_room_thing_is_on(thing); if (creature_work_in_room_no_longer_possible(room, RoK_PRISON, thing)) { remove_creature_from_work_room(thing); set_start_state(thing); return CrStRet_ResetFail; } if (room->used_capacity > room->total_capacity) { output_message_room_related_from_computer_or_player_action(room->owner, room->kind, OMsg_RoomTooSmall); set_start_state(thing); return CrStRet_ResetOk; } switch (process_prison_function(thing)) { case CrCkRet_Deleted: return CrStRet_Deleted; case CrCkRet_Available: process_prison_visuals(thing, room); return CrStRet_Modified; default: return CrStRet_ResetOk; } }
short at_workshop_room(struct Thing *thing) { struct CreatureControl *cctrl; struct Room *room; //return _DK_at_workshop_room(thing); cctrl = creature_control_get_from_thing(thing); cctrl->target_room_id = 0; room = get_room_thing_is_on(thing); if (!room_initially_valid_as_type_for_thing(room, RoK_WORKSHOP, thing)) { WARNLOG("Room %s owned by player %d is invalid for %s",room_code_name(room->kind),(int)room->owner,thing_model_name(thing)); set_start_state(thing); return 0; } if (room->total_capacity <= room->used_capacity) { set_start_state(thing); return 0; } if ( !add_creature_to_work_room(thing, room) ) { set_start_state(thing); return 0; } internal_set_thing_state(thing, CrSt_Manufacturing); setup_move_to_new_workshop_position(thing, room, 1); return 1; }
short creature_sleep(struct Thing *thing) { //return _DK_creature_sleep(thing); struct CreatureControl *cctrl; cctrl = creature_control_get_from_thing(thing); if ((cctrl->slap_turns > 0) || !creature_will_sleep(thing)) { set_start_state(thing); return 0; } struct Room *room; room = get_room_thing_is_on(thing); if (room_is_invalid(room) || (room->kind != RoK_LAIR) || (cctrl->lair_room_id != room->index) || (room->owner != thing->owner)) { set_start_state(thing); return 0; } thing->movement_flags &= ~0x0020; struct CreatureStats *crstat; crstat = creature_stats_get_from_thing(thing); if (((game.play_gameturn + thing->index) % game.recovery_frequency) == 0) { HitPoints recover; recover = compute_creature_max_health(crstat->sleep_recovery, cctrl->explevel); apply_health_to_thing_and_display_health(thing, recover); } anger_set_creature_anger(thing, 0, AngR_NoLair); anger_apply_anger_to_creature(thing, crstat->annoy_sleeping, AngR_Other, 1); if (cctrl->field_82 > 0) { cctrl->field_82--; } if (((game.play_gameturn + thing->index) & 0x3F) == 0) { if (ACTION_RANDOM(100) < 5) { struct Dungeon *dungeon; dungeon = get_dungeon(thing->owner); dungeon->lvstats.backs_stabbed++; } } if (crstat->sleep_exp_slab != SlbT_ROCK) { if (creature_can_gain_experience(thing) && room_has_slab_adjacent(room, crstat->sleep_exp_slab)) { cctrl->exp_points += crstat->sleep_experience; check_experience_upgrade(thing); } } { HitPoints health_max; health_max = compute_creature_max_health(crstat->health, cctrl->explevel); if ((crstat->heal_threshold * health_max / 256 <= thing->health) && (!cctrl->field_82)) { set_start_state(thing); return 1; } } process_lair_enemy(thing, room); return 0; }
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; }
TbBool prison_convert_creature_to_skeleton(struct Room *room, struct Thing *thing) { struct Dungeon *dungeon; struct CreatureControl *cctrl; struct Thing *crthing; long crmodel; cctrl = creature_control_get_from_thing(thing); crmodel = get_room_create_creature_model(room->kind); // That normally returns skeleton breed crthing = create_creature(&thing->mappos, crmodel, room->owner); if (thing_is_invalid(crthing)) { ERRORLOG("Couldn't create creature %s in prison", creature_code_name(crmodel)); return false; } init_creature_level(crthing, cctrl->explevel); set_start_state(crthing); if (creature_model_bleeds(thing->model)) create_effect_around_thing(thing, TngEff_Unknown10); kill_creature(thing, INVALID_THING, -1, CrDed_NoEffects); dungeon = get_dungeon(room->owner); if (!dungeon_invalid(dungeon)) { dungeon->lvstats.skeletons_raised++; } return true; }
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 good_drops_gold(struct Thing *thing) { // Debug code to find incorrect states if (!is_hero_thing(thing)) { ERRORLOG("Non hero thing %ld, %s, owner %ld - reset",(long)thing->index,thing_model_name(thing),(long)thing->owner); set_start_state(thing); erstat_inc(ESE_BadCreatrState); return 0; } //return _DK_good_drops_gold(thing); GoldAmount amount; amount = game.pot_of_gold_holds; if (thing->creature.gold_carried <= game.pot_of_gold_holds) amount = thing->creature.gold_carried; struct Thing *gldtng; gldtng = create_object(&thing->mappos, 6, thing->owner, -1); if (thing_is_invalid(gldtng)) { return 0; } gldtng->valuable.gold_stored = amount; thing->creature.gold_carried -= amount; // Update size of the gold object add_gold_to_pile(gldtng, 0); internal_set_thing_state(thing, CrSt_GoodBackAtStart); return 1; }
short good_leave_through_exit_door(struct Thing *thing) { struct CreatureControl *cctrl; struct Thing *tmptng; // Debug code to find incorrect states if (!is_hero_thing(thing)) { ERRORLOG("Non hero thing %ld, %s, owner %ld - reset",(long)thing->index,thing_model_name(thing),(long)thing->owner); set_start_state(thing); erstat_inc(ESE_BadCreatrState); return false; } //return _DK_good_leave_through_exit_door(thing); tmptng = find_base_thing_on_mapwho(TCls_Object, 49, thing->mappos.x.stl.num, thing->mappos.y.stl.num); if (thing_is_invalid(tmptng)) { return 0; } cctrl = creature_control_get_from_thing(thing); thing->creature.gold_carried = 0; cctrl->field_282 = game.hero_door_wait_time; cctrl->byte_8A = tmptng->creation_turn; place_thing_in_creature_controlled_limbo(thing); internal_set_thing_state(thing, CrSt_GoodWaitInExitDoor); return 1; }
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; }
struct Thing *create_and_control_creature_as_controller(struct PlayerInfo *player, long breed, struct Coord3d *pos) { struct CreatureStats *crstat; struct CreatureControl *cctrl; struct Dungeon *dungeon; struct Thing *thing; struct Camera *cam; struct InitLight ilght; SYNCDBG(6,"Request for model %ld at (%d,%d,%d)",breed,(int)pos->x.val,(int)pos->y.val,(int)pos->z.val); //return _DK_create_and_control_creature_as_controller(player, a2, pos); thing = create_creature(pos, breed, player->id_number); if (thing_is_invalid(thing)) return INVALID_THING; dungeon = get_dungeon(thing->owner); dungeon->num_active_creatrs--; dungeon->owned_creatures_of_model[thing->model]--; if (is_my_player(player)) { toggle_status_menu(0); turn_off_roaming_menus(); } cam = player->acamera; player->controlled_thing_idx = thing->index; player->field_31 = thing->creation_turn; player->field_4B5 = cam->field_6; thing->alloc_flags |= TAlF_IsControlled; thing->field_4F |= 0x01; cctrl = creature_control_get_from_thing(thing); cctrl->flgfield_2 |= 0x02; cctrl->max_speed = calculate_correct_creature_maxspeed(thing); set_player_mode(player, PVT_CreatureContrl); set_start_state(thing); // Preparing light object LbMemorySet(&ilght, 0, sizeof(struct InitLight)); ilght.mappos.x.val = thing->mappos.x.val; ilght.mappos.y.val = thing->mappos.y.val; ilght.mappos.z.val = thing->mappos.z.val; ilght.field_2 = 36; ilght.field_3 = 1; ilght.is_dynamic = 1; ilght.field_0 = 2560; thing->light_id = light_create_light(&ilght); if (thing->light_id != 0) { light_set_light_never_cache(thing->light_id); } else { ERRORLOG("Cannot allocate light to new hero"); } if (is_my_player_number(thing->owner)) { if (thing->class_id == TCls_Creature) { crstat = creature_stats_get_from_thing(thing); setup_eye_lens(crstat->eye_effect); } } return thing; }
short manufacturing(struct Thing *creatng) { struct Room *room; //return _DK_manufacturing(creatng); TRACE_THING(creatng); room = get_room_thing_is_on(creatng); if (creature_work_in_room_no_longer_possible(room, RoK_WORKSHOP, creatng)) { remove_creature_from_work_room(creatng); set_start_state(creatng); return CrStRet_ResetFail; } if (room->used_capacity > room->total_capacity) { if (is_my_player_number(creatng->owner)) output_message(SMsg_WorkshopTooSmall, 500, true); remove_creature_from_work_room(creatng); set_start_state(creatng); return CrStRet_ResetOk; } struct Dungeon *dungeon; dungeon = get_dungeon(creatng->owner); if (dungeon->manufacture_class) { struct CreatureControl *cctrl; struct CreatureStats *crstat; cctrl = creature_control_get_from_thing(creatng); crstat = creature_stats_get_from_thing(creatng); long work_value; work_value = compute_creature_work_value(crstat->manufacture_value*256, room->efficiency, cctrl->explevel); work_value = process_work_speed_on_work_value(creatng, work_value); SYNCDBG(9,"The %s index %d produced %d manufacture points",thing_model_name(creatng),(int)creatng->index,(int)work_value); dungeon->manufacture_progress += work_value; dungeon->field_1181 += work_value; } else { WARNDBG(9,"The %s index %d owner %d is manufacturing nothing",thing_model_name(creatng),(int)creatng->index,(int)creatng->owner); // This may be cause by a creature taking up place in workshop where crate should be created; the creature should take a break if (room->used_capacity >= room->total_capacity) { external_set_thing_state(creatng, CrSt_CreatureGoingHomeToSleep); return CrStRet_Modified; } } process_creature_in_workshop(creatng, room); return CrStRet_Modified; }
short at_lair_to_sleep(struct Thing *thing) { struct CreatureControl *cctrl; struct Thing *lairtng; struct Room *room; TRACE_THING(thing); //return _DK_at_lair_to_sleep(thing); cctrl = creature_control_get_from_thing(thing); lairtng = thing_get(cctrl->lairtng_idx); TRACE_THING(lairtng); cctrl->target_room_id = 0; if (thing_is_invalid(lairtng) || (cctrl->slap_turns != 0)) { set_start_state(thing); return 0; } if (!creature_will_sleep(thing)) { set_start_state(thing); return 0; } room = get_room_thing_is_on(thing); if (!room_initially_valid_as_type_for_thing(room, RoK_LAIR, thing)) { WARNLOG("Room %s owned by player %d is invalid for %s",room_code_name(room->kind),(int)room->owner,thing_model_name(thing)); set_start_state(thing); return 0; } if ((cctrl->lair_room_id != room->index)) { set_start_state(thing); return 0; } if ( !creature_turn_to_face_angle(thing, lairtng->field_52) ) { internal_set_thing_state(thing, CrSt_CreatureSleep); cctrl->field_82 = 200; thing->movement_flags &= ~TMvF_Flying; } process_lair_enemy(thing, room); return 1; }
short at_research_room(struct Thing *thing) { struct CreatureControl *cctrl; struct Dungeon *dungeon; struct Room *room; cctrl = creature_control_get_from_thing(thing); cctrl->target_room_id = 0; dungeon = get_dungeon(thing->owner); if (!creature_can_do_research(thing)) { if (!is_neutral_thing(thing) && (dungeon->current_research_idx < 0)) { if (is_my_player_number(dungeon->owner)) output_message(SMsg_NoMoreReseach, 500, true); } set_start_state(thing); return 0; } room = get_room_thing_is_on(thing); if (!room_initially_valid_as_type_for_thing(room, RoK_LIBRARY, thing)) { WARNLOG("Room %s owned by player %d is invalid for %s index %d",room_code_name(room->kind),(int)room->owner,thing_model_name(thing),(int)thing->index); set_start_state(thing); return 0; } if (!add_creature_to_work_room(thing, room)) { set_start_state(thing); return 0; } if (!setup_random_head_for_room(thing, room, NavRtF_Default)) { ERRORLOG("The %s index %d can not move in research room", thing_model_name(thing),(int)thing->index); remove_creature_from_work_room(thing); set_start_state(thing); return 0; } thing->continue_state = CrSt_Researching; cctrl->field_82 = 0; cctrl->byte_9A = 3; return 1; }
CrStateRet creature_at_new_lair(struct Thing *creatng) { struct Room *room; TRACE_THING(creatng); //return _DK_creature_at_new_lair(thing); room = get_room_thing_is_on(creatng); if ( !room_still_valid_as_type_for_thing(room, RoK_LAIR, creatng) ) { WARNLOG("Room %s owned by player %d is bad work place for %s owned by played %d",room_code_name(room->kind),(int)room->owner,thing_model_name(creatng),(int)creatng->owner); set_start_state(creatng); return CrStRet_ResetFail; } if (!creature_add_lair_to_room(creatng, room)) { internal_set_thing_state(creatng, CrSt_CreatureChooseRoomForLairSite); return CrStRet_Modified; } set_start_state(creatng); return CrStRet_ResetOk; }
short at_training_room(struct Thing *thing) { struct CreatureControl *cctrl; struct CreatureStats *crstat; struct Dungeon *dungeon; struct Room *room; //return _DK_at_training_room(thing); cctrl = creature_control_get_from_thing(thing); cctrl->target_room_id = 0; if (!creature_can_be_trained(thing)) { SYNCDBG(9,"Ending training of %s level %d; creature is not trainable",thing_model_name(thing),(int)cctrl->explevel); set_start_state(thing); return 0; } crstat = creature_stats_get_from_thing(thing); dungeon = get_dungeon(thing->owner); if (dungeon->total_money_owned < crstat->training_cost) { if (is_my_player_number(thing->owner)) output_message(SMsg_NoGoldToTrain, MESSAGE_DELAY_TREASURY, true); set_start_state(thing); return 0; } room = get_room_thing_is_on(thing); if (!room_initially_valid_as_type_for_thing(room, RoK_TRAINING, thing)) { WARNLOG("Room %s owned by player %d is invalid for %s",room_code_name(room->kind),(int)room->owner,thing_model_name(thing)); set_start_state(thing); return 0; } if ( !add_creature_to_work_room(thing, room) ) { set_start_state(thing); return 0; } internal_set_thing_state(thing, CrSt_Training); setup_move_to_new_training_position(thing, room, 1); cctrl->field_82 = 0; return 1; }
short good_wait_in_exit_door(struct Thing *thing) { struct CreatureControl *cctrl; struct Thing *tmptng; // Debug code to find incorrect states if (!is_hero_thing(thing)) { ERRORLOG("Non hero thing %s index %d, owner %d - reset", thing_model_name(thing), (int)thing->index, (int)thing->owner); set_start_state(thing); erstat_inc(ESE_BadCreatrState); return 0; } //return _DK_good_wait_in_exit_door(thing); cctrl = creature_control_get_from_thing(thing); if (cctrl->field_282 <= 0) return 0; cctrl->field_282--; if (cctrl->field_282 == 0) { tmptng = find_base_thing_on_mapwho(TCls_Object, 49, thing->mappos.x.stl.num, thing->mappos.y.stl.num); if (!thing_is_invalid(tmptng)) { if (cctrl->byte_8A == tmptng->creation_turn) { remove_thing_from_creature_controlled_limbo(thing); set_start_state(thing); return 1; } } thing->creature.gold_carried = 0; tmptng = thing_get(cctrl->dragtng_idx); TRACE_THING(tmptng); if (!thing_is_invalid(tmptng)) { delete_thing_structure(tmptng, 0); } kill_creature(thing, INVALID_THING, -1, CrDed_NoEffects|CrDed_NotReallyDying); } return 0; }
short good_back_at_start(struct Thing *thing) { // Debug code to find incorrect states if (!is_hero_thing(thing)) { ERRORLOG("Non hero thing %ld, %s, owner %ld - reset",(long)thing->index,thing_model_name(thing),(long)thing->owner); set_start_state(thing); return false; } //return _DK_good_back_at_start(thing); if (thing->creature.gold_carried <= 0) { set_start_state(thing); return 1; } SubtlCodedCoords stl_num; long m,n; stl_num = get_subtile_number(thing->mappos.x.stl.num,thing->mappos.y.stl.num); m = ACTION_RANDOM(AROUND_MAP_LENGTH); for (n=0; n < AROUND_MAP_LENGTH; n++) { struct Map *mapblk; mapblk = get_map_block_at_pos(stl_num+around_map[m]); // Per-block code if ((mapblk->flags & MapFlg_IsTall) == 0) { MapSubtlCoord stl_x, stl_y; stl_x = stl_num_decode_x(stl_num+around_map[m]); stl_y = stl_num_decode_y(stl_num+around_map[m]); if (setup_person_move_to_position(thing, stl_x, stl_y, NavRtF_Default)) { thing->continue_state = CrSt_GoodDropsGold; return 1; } } // Per-block code ends m = (m + 1) % AROUND_MAP_LENGTH; } set_start_state(thing); return 1; }
short creature_choose_room_for_lair_site(struct Thing *thing) { TRACE_THING(thing); //return _DK_creature_choose_room_for_lair_site(thing); struct Room *room; room = get_best_new_lair_for_creature(thing); if (room_is_invalid(room)) { update_cannot_find_room_wth_spare_capacity_event(thing->owner, thing, RoK_LAIR); set_start_state(thing); return 0; } if (!setup_head_for_random_unused_lair_slab(thing, room)) { ERRORLOG("Chosen lair is not valid, internal inconsistency."); set_start_state(thing); return 0; } thing->continue_state = CrSt_CreatureAtNewLair; return 1; }
void creature_stop_affected_by_call_to_arms(struct Thing *thing) { struct CreatureControl *cctrl; cctrl = creature_control_get_from_thing(thing); cctrl->spell_flags &= ~CSAfF_CalledToArms; if (!thing_is_picked_up(thing) && !creature_is_being_unconscious(thing)) { if (creature_is_called_to_arms(thing)) { set_start_state(thing); } } }
short at_barrack_room(struct Thing *creatng) { struct Room *room; struct CreatureControl *cctrl; cctrl = creature_control_get_from_thing(creatng); cctrl->target_room_id = 0; room = get_room_thing_is_on(creatng); if (!room_initially_valid_as_type_for_thing(room, RoK_BARRACKS, creatng)) { WARNLOG("Room %s owned by player %d is invalid for %s index %d",room_code_name(room->kind),(int)room->owner,thing_model_name(creatng),(int)creatng->index); set_start_state(creatng); return 0; } if (!add_creature_to_work_room(creatng, room)) { set_start_state(creatng); return 0; } internal_set_thing_state(creatng, CrSt_Barracking); return 1; }
short creature_arrived_at_prison(struct Thing *creatng) { struct CreatureControl *cctrl; struct Room *room; TRACE_THING(creatng); cctrl = creature_control_get_from_thing(creatng); cctrl->target_room_id = 0; room = get_room_thing_is_on(creatng); if (!room_initially_valid_as_type_for_thing(room, RoK_PRISON, creatng)) { WARNLOG("Room %s owned by player %d is invalid for %s index %d",room_code_name(room->kind),(int)room->owner,thing_model_name(creatng),(int)creatng->index); set_start_state(creatng); return 0; } if (!add_creature_to_work_room(creatng, room)) { output_message_room_related_from_computer_or_player_action(room->owner, room->kind, OMsg_RoomTooSmall); cctrl->flgfield_1 &= ~CCFlg_NoCompControl; set_start_state(creatng); return 0; } cctrl->field_82 = game.play_gameturn; cctrl->flgfield_1 |= CCFlg_NoCompControl; internal_set_thing_state(creatng, CrSt_CreatureInPrison); if (creature_affected_by_spell(creatng, SplK_Speed)) { terminate_thing_spell_effect(creatng, SplK_Speed); } if (creature_affected_by_spell(creatng, SplK_Invisibility)) { terminate_thing_spell_effect(creatng, SplK_Invisibility); } if (creatng->light_id != 0) { light_delete_light(creatng->light_id); creatng->light_id = 0; } return 1; }
/** * Does a step of researching. * Informs if the research cycle should end. * @param thing */ CrCheckRet process_research_function(struct Thing *creatng) { struct Dungeon *dungeon; struct Room *room; dungeon = get_dungeon(creatng->owner); if (dungeon_invalid(dungeon)) { SYNCDBG(9,"The %s index %d cannot work as player %d has no dungeon", thing_model_name(creatng), (int)creatng->index, (int)creatng->owner); set_start_state(creatng); return CrCkRet_Continue; } if (!creature_can_do_research(creatng)) { set_start_state(creatng); return CrCkRet_Continue; } room = get_room_creature_works_in(creatng); if ( !room_still_valid_as_type_for_thing(room, RoK_LIBRARY, creatng) ) { WARNLOG("Room %s owned by player %d is bad work place for %s index %d owner %d", room_code_name(room->kind), (int)room->owner, thing_model_name(creatng),(int)creatng->index,(int)creatng->owner); set_start_state(creatng); return CrCkRet_Continue; } long work_value; struct CreatureControl *cctrl; cctrl = creature_control_get_from_thing(creatng); struct CreatureStats *crstat; crstat = creature_stats_get_from_thing(creatng); work_value = compute_creature_work_value(crstat->research_value*256, room->efficiency, cctrl->explevel); work_value = process_work_speed_on_work_value(creatng, work_value); SYNCDBG(19,"The %s index %d produced %d research points",thing_model_name(creatng),(int)creatng->index,(int)work_value); dungeon->total_research_points += work_value; dungeon->research_progress += work_value; //TODO CREATURE_JOBS going postal should be possible for all jobs, not only research process_job_stress_and_going_postal(creatng, room); return CrCkRet_Available; }