TbBool placing_offmap_workshop_item(PlayerNumber plyr_idx, ThingClass tngclass, ThingModel tngmodel) { SYNCDBG(18,"Starting"); struct Dungeon *dungeon; dungeon = get_players_num_dungeon(plyr_idx); if (dungeon_invalid(dungeon)) { // Player with no dungeon has only on-map items // But this shouldn't really happen return true; } switch (tngclass) { case TCls_Trap: if (dungeon->trap_amount_stored[tngmodel] > 0) { return false; } if (dungeon->trap_amount_offmap[tngmodel] > 0) { return true; } break; case TCls_Door: if (dungeon->door_amount_stored[tngmodel] > 0) { return false; } if (dungeon->door_amount_offmap[tngmodel] > 0) { return true; } break; } return false; }
TbBool creature_can_do_barracking_for_player(const struct Thing *creatng, PlayerNumber plyr_idx, CreatureJob new_job) { // Grouping or barracking only makes sense if we have more than one creature const struct Dungeon *dungeon; dungeon = get_players_num_dungeon(plyr_idx); return (dungeon->num_active_creatrs > 1); }
/** Returns if given player owns a room of given kind. * * @param plyr_idx * @param rkind Room kind being checked. * @return */ TbBool player_has_room(PlayerNumber plyr_idx, RoomKind rkind) { struct Dungeon *dungeon; if (plyr_idx == game.neutral_player_num) return false; dungeon = get_players_num_dungeon(plyr_idx); return (dungeon->room_kind[rkind] > 0); }
struct Thing *get_player_soul_container(PlayerNumber plyr_idx) { struct Dungeon *dungeon; dungeon = get_players_num_dungeon(plyr_idx); if (dungeon->dnheart_idx > 0) { return thing_get(dungeon->dnheart_idx); } return INVALID_THING; }
struct Room *player_has_room_of_type(PlayerNumber plyr_idx, RoomKind rkind) { //return _DK_player_has_room_of_type(plyr_idx, rkind); struct Dungeon *dungeon; if (plyr_idx == game.neutral_player_num) return false; dungeon = get_players_num_dungeon(plyr_idx); return room_get(dungeon->room_kind[rkind]); }
void frontstats_save_high_score(void) { struct Dungeon *dungeon; dungeon = get_players_num_dungeon(my_player_number); if (dungeon->lvstats.allow_save_score) { dungeon->lvstats.allow_save_score = false; add_score_to_high_score_table(); } lbInkey = 0; }
const struct Coord3d *dungeon_get_essential_pos(PlayerNumber plyr_idx) { struct Dungeon *dungeon; dungeon = get_players_num_dungeon(plyr_idx); if (dungeon->dnheart_idx > 0) { struct Thing *heartng; heartng = thing_get(dungeon->dnheart_idx); if (thing_exists(heartng)) { return &heartng->mappos; } } return &dungeon->essential_pos; }
void turn_off_event_box_if_necessary(PlayerNumber plyr_idx, unsigned char event_idx) { struct Dungeon *dungeon; dungeon = get_players_num_dungeon(plyr_idx); if (dungeon->visible_event_idx != event_idx) { return; } dungeon->visible_event_idx = 0; if (is_my_player_number(plyr_idx)) { turn_off_menu(GMnu_TEXT_INFO); turn_off_menu(GMnu_BATTLE); turn_off_menu(GMnu_DUNGEON_SPECIAL); } }
TbBool check_workshop_item_limit_reached(PlayerNumber plyr_idx, ThingClass tngclass, ThingModel tngmodel) { struct Dungeon *dungeon; dungeon = get_players_num_dungeon(plyr_idx); if (dungeon_invalid(dungeon)) return true; switch (tngclass) { case TCls_Trap: return (dungeon->trap_amount_stored[tngmodel] >= MANUFACTURED_ITEMS_LIMIT); case TCls_Door: return (dungeon->door_amount_stored[tngmodel] >= MANUFACTURED_ITEMS_LIMIT); } return true; }
/** * Returns if the trap was at least one built by a player. */ TbBool is_trap_built(PlayerNumber plyr_idx, long tngmodel) { struct Dungeon *dungeon; dungeon = get_players_num_dungeon(plyr_idx); // Check if the player even have a dungeon if (dungeon_invalid(dungeon)) { return false; } if ((tngmodel <= 0) || (tngmodel >= TRAP_TYPES_COUNT)) { ERRORLOG("Incorrect trap %d (player %d)",(int)tngmodel, (int)plyr_idx); return false; } if ((dungeon->trap_build_flags[tngmodel] & MnfBldF_Built) != 0) { return true; } return false; }
TbBool player_creature_tends_to(PlayerNumber plyr_idx, unsigned short tend_type) { const struct Dungeon *dungeon; if (plyr_idx == game.neutral_player_num) return false; dungeon = get_players_num_dungeon(plyr_idx); switch (tend_type) { case CrTend_Imprison: return ((dungeon->creature_tendencies & 0x01) != 0); case CrTend_Flee: return ((dungeon->creature_tendencies & 0x02) != 0); default: ERRORLOG("Bad tendency type %d",(int)tend_type); return false; } }
/** * Returns if the trap can be placed by a player. * Checks only if it's available and if the player is 'alive'. * Doesn't check if map position is on correct spot. */ TbBool is_trap_placeable(PlayerNumber plyr_idx, long tngmodel) { struct Dungeon *dungeon; dungeon = get_players_num_dungeon(plyr_idx); // Check if the player even have a dungeon if (dungeon_invalid(dungeon)) { return false; } // Player must have dungeon heart to place traps if (!player_has_heart(plyr_idx)) { return false; } if ((tngmodel <= 0) || (tngmodel >= TRAP_TYPES_COUNT)) { ERRORLOG("Incorrect trap %d (player %d)",(int)tngmodel, (int)plyr_idx); return false; } if (dungeon->trap_amount_placeable[tngmodel] > 0) { return true; } return false; }
/** * Returns if the door was at least one built by a player. */ TbBool is_door_built(PlayerNumber plyr_idx, long door_idx) { struct Dungeon *dungeon; dungeon = get_players_num_dungeon(plyr_idx); // Check if the player even have a dungeon if (dungeon_invalid(dungeon)) { return false; } // Player must have dungeon heart to build anything if (!player_has_heart(plyr_idx)) { return false; } if ((door_idx <= 0) || (door_idx >= DOOR_TYPES_COUNT)) { ERRORLOG("Incorrect door %d (player %d)",(int)door_idx, (int)plyr_idx); return false; } if ((dungeon->door_build_flags[door_idx] & MnfBldF_Built) != 0) { return true; } return false; }
/** * Returns if the trap can be manufactured by a player. * Checks only if it's set as buildable in level script. * Doesn't check if player has workshop or workforce for the task. */ TbBool is_trap_buildable(PlayerNumber plyr_idx, long tngmodel) { struct Dungeon *dungeon; dungeon = get_players_num_dungeon(plyr_idx); // Check if the player even have a dungeon if (dungeon_invalid(dungeon)) { return false; } // Player must have dungeon heart to build anything if (!player_has_heart(plyr_idx)) { return false; } if ((tngmodel <= 0) || (tngmodel >= TRAP_TYPES_COUNT)) { ERRORLOG("Incorrect trap %d (player %d)",(int)tngmodel, (int)plyr_idx); return false; } if ((dungeon->trap_build_flags[tngmodel] & MnfBldF_Manufacturable) != 0) { return true; } return false; }
struct Room *get_opponent_room(struct Computer2 *comp, PlayerNumber plyr_idx) { static const RoomKind opponent_room_kinds[] = {RoK_DUNGHEART, RoK_PRISON, RoK_LIBRARY, RoK_TREASURE}; struct Dungeon *dungeon; struct Room *room; dungeon = get_players_num_dungeon(plyr_idx); if (dungeon_invalid(dungeon) || (slab_conf.room_types_count < 1)) { return INVALID_ROOM; } int i,n; n = opponent_room_kinds[ACTION_RANDOM(sizeof(opponent_room_kinds)/sizeof(opponent_room_kinds[0]))]; for (i=0; i < slab_conf.room_types_count; i++) { room = room_get(dungeon->room_kind[n]); if (room_exists(room)) { return room; } n = (n + 1) % slab_conf.room_types_count; } return INVALID_ROOM; }
void resurrect_creature(struct Thing *boxtng, PlayerNumber owner, ThingModel crmodel, unsigned char crlevel) { struct Thing *creatng; if (!thing_exists(boxtng) || (box_thing_to_special(boxtng) != SpcKind_Resurrect) ) { ERRORMSG("Invalid resurrect box object!"); return; } creatng = create_creature(&boxtng->mappos, crmodel, owner); if (!thing_is_invalid(creatng)) { init_creature_level(creatng, crlevel); if (is_my_player_number(owner)) output_message(SMsg_CommonAcknowledge, 0, true); } create_special_used_effect(&boxtng->mappos, owner); remove_events_thing_is_attached_to(boxtng); force_any_creature_dragging_owned_thing_to_drop_it(boxtng); if ((gameadd.classic_bugs_flags & ClscBug_ResurrectForever) == 0) { remove_item_from_dead_creature_list(get_players_num_dungeon(owner), crmodel, crlevel); } delete_thing_structure(boxtng, 0); }
TbBool attempt_anger_job_persuade(struct Thing *creatng) { struct CreatureControl *cctrl; cctrl = creature_control_get_from_thing(creatng); if (cctrl->explevel <= 5) { return false; } if (!can_change_from_state_to(creatng, creatng->active_state, CrSt_CreaturePersuade)) { return false; } struct Dungeon *dungeon; dungeon = get_players_num_dungeon(creatng->owner); int persuade_count; persuade_count = min(dungeon->num_active_creatrs-1, 5); if (persuade_count <= 0) { return false; } persuade_count = ACTION_RANDOM(persuade_count) + 1; if (!external_set_thing_state(creatng, CrSt_CreaturePersuade)) { return false; } cctrl->byte_9A = persuade_count; return true; }
void redraw_isometric_view(void) { struct PlayerInfo *player; struct Dungeon *dungeon; TbGraphicsWindow ewnd; struct Coord3d pos; SYNCDBG(6,"Starting"); player = get_my_player(); if (player->acamera == NULL) return; memcpy(&pos,&player->acamera->mappos,sizeof(struct Coord3d)); LbMemorySet(&ewnd, 0, sizeof(TbGraphicsWindow)); if (player->field_45F != 1) player->field_45F = 1; dungeon = get_players_num_dungeon(my_player_number); // Camera position modifications make_camera_deviations(player,dungeon); update_explored_flags_for_power_sight(player); if ((game.flags_font & FFlg_unk08) != 0) { store_engine_window(&ewnd,1); setup_engine_window(ewnd.x, ewnd.y, ewnd.width >> 1, ewnd.height >> 1); }
short process_player_manufacturing(PlayerNumber plyr_idx) { struct Dungeon *dungeon; struct Room *room; int k; SYNCDBG(7,"Starting for player %d",(int)plyr_idx); dungeon = get_players_num_dungeon(plyr_idx); if (!player_has_room_of_role(plyr_idx, RoRoF_CratesManufctr)) { return true; } if (dungeon->manufacture_class == TCls_Empty) { get_next_manufacture(dungeon); return true; } k = manufacture_points_required(dungeon->manufacture_class, dungeon->manufacture_kind); // If we don't have enough manufacture points, don't do anything if (dungeon->manufacture_progress < (k << 8)) return true; // Try to do the manufacturing room = find_room_with_spare_room_item_capacity(plyr_idx, RoK_WORKSHOP); if (room_is_invalid(room)) { dungeon->manufacture_class = TCls_Empty; return false; } if (check_workshop_item_limit_reached(plyr_idx, dungeon->manufacture_class, dungeon->manufacture_kind)) { ERRORLOG("Bad choice for manufacturing - limit reached for %s kind %d",thing_class_code_name(dungeon->manufacture_class),(int)dungeon->manufacture_kind); get_next_manufacture(dungeon); return false; } if (create_workshop_object_in_workshop_room(plyr_idx, dungeon->manufacture_class, dungeon->manufacture_kind) == 0) { ERRORLOG("Could not create manufactured %s kind %d",thing_class_code_name(dungeon->manufacture_class),(int)dungeon->manufacture_kind); return false; } add_workshop_item_to_amounts(plyr_idx, dungeon->manufacture_class, dungeon->manufacture_kind); switch (dungeon->manufacture_class) { case TCls_Trap: dungeon->lvstats.manufactured_traps++; // If that's local player - make a message if (is_my_player_number(plyr_idx)) output_message(SMsg_ManufacturedTrap, 0, true); break; case TCls_Door: dungeon->lvstats.manufactured_doors++; // If that's local player - make a message if (is_my_player_number(plyr_idx)) output_message(SMsg_ManufacturedDoor, 0, true); break; default: ERRORLOG("Invalid type of new manufacture, %d",(int)dungeon->manufacture_class); return false; } dungeon->manufacture_progress -= (k << 8); dungeon->field_118B = game.play_gameturn; dungeon->lvstats.manufactured_items++; get_next_manufacture(dungeon); return true; }
TbBool create_workshop_object_in_workshop_room(PlayerNumber plyr_idx, ThingClass tngclass, ThingModel tngmodel) { struct Coord3d pos; struct Thing *cratetng; struct Room *room; struct Dungeon *dungeon; SYNCDBG(7,"Making player %d new %s",(int)plyr_idx,thing_class_code_name(tngclass)); pos.x.val = 0; pos.y.val = 0; pos.z.val = 0; switch (tngclass) { case TCls_Trap: cratetng = create_object(&pos, trap_crate_object_model(tngmodel), plyr_idx, -1); break; case TCls_Door: cratetng = create_object(&pos, door_crate_object_model(tngmodel), plyr_idx, -1); break; default: cratetng = INVALID_THING; ERRORLOG("No known workshop crate can represent %s model %d",thing_class_code_name(tngclass),(int)tngmodel); break; } if (thing_is_invalid(cratetng)) { ERRORLOG("Could not create workshop crate thing for %s",thing_class_code_name(tngclass)); return false; } room = find_random_room_for_thing_with_spare_room_item_capacity(cratetng, plyr_idx, RoK_WORKSHOP, 0); if (room_is_invalid(room)) { ERRORLOG("No %s room found which would accept %s crate",room_code_name(RoK_WORKSHOP),thing_class_code_name(tngclass)); destroy_object(cratetng); return false; } if (!find_random_valid_position_for_thing_in_room_avoiding_object(cratetng, room, &pos)) { ERRORLOG("Could not find a place in %s index %d for the new %s crate", room_code_name(room->kind),(int)room->index,thing_class_code_name(tngclass)); destroy_object(cratetng); return false; } pos.z.val = get_thing_height_at(cratetng, &pos); move_thing_in_map(cratetng, &pos); if (!add_workshop_object_to_workshop(room, cratetng)) { ERRORLOG("Could not fit %s crate in %s index %d", thing_class_code_name(tngclass),room_code_name(room->kind),(int)room->index); destroy_object(cratetng); return false; } dungeon = get_players_num_dungeon(plyr_idx); switch (tngclass) { case TCls_Trap: if ((dungeon->trap_build_flags[tngmodel] & MnfBldF_Built) == 0) { event_create_event(cratetng->mappos.x.val, cratetng->mappos.y.val, EvKind_NewTrap, plyr_idx, tngmodel); } break; case TCls_Door: if ((dungeon->door_build_flags[tngmodel] & MnfBldF_Built) == 0) { event_create_event(cratetng->mappos.x.val, cratetng->mappos.y.val, EvKind_NewDoor, plyr_idx, tngmodel); } break; default: break; } create_effect(&pos, TngEff_Unknown56, cratetng->owner); thing_play_sample(cratetng, 89, NORMAL_PITCH, 0, 3, 0, 2, FULL_LOUDNESS); return true; }
TbBool steal_hero(struct PlayerInfo *player, struct Coord3d *pos) { //TODO CONFIG creature models dependency; put them in config files static ThingModel skip_steal_models[] = {6, 7}; static ThingModel prefer_steal_models[] = {3, 12}; struct Thing *herotng; herotng = INVALID_THING; int heronum; struct Dungeon *herodngn; struct CreatureControl *cctrl; unsigned long k; int i; SYNCDBG(8,"Starting"); herodngn = get_players_num_dungeon(game.hero_player_num); k = 0; if (herodngn->num_active_creatrs > 0) { heronum = ACTION_RANDOM(herodngn->num_active_creatrs); i = herodngn->creatr_list_start; SYNCDBG(4,"Selecting random creature %d out of %d heroes",(int)heronum,(int)herodngn->num_active_creatrs); } else { heronum = 0; i = 0; SYNCDBG(4,"No heroes on map, skipping selection"); } while (i != 0) { struct Thing *thing; thing = thing_get(i); TRACE_THING(thing); cctrl = creature_control_get_from_thing(thing); if (thing_is_invalid(thing) || creature_control_invalid(cctrl)) { ERRORLOG("Jump to invalid creature detected"); break; } i = cctrl->players_next_creature_idx; // Thing list loop body TbBool heroallow; heroallow = true; ThingModel skipidx; for (skipidx=0; skipidx < sizeof(skip_steal_models)/sizeof(skip_steal_models[0]); skipidx++) { if (thing->model == skip_steal_models[skipidx]) { heroallow = false; } } if (heroallow) { herotng = thing; } // If we've reached requested hero number, return either current hero on previously selected one if ((heronum <= 0) && thing_is_creature(herotng)) { break; } heronum--; if (i == 0) { i = herodngn->creatr_list_start; } // Thing list loop body ends k++; if (k > CREATURES_COUNT) { ERRORLOG("Infinite loop detected when sweeping creatures list"); erstat_inc(ESE_InfChainTngPerOwner); break; } } if (!thing_is_invalid(herotng)) { move_thing_in_map(herotng, pos); change_creature_owner(herotng, player->id_number); SYNCDBG(3,"Converted %s to owner %d",thing_model_name(herotng),(int)player->id_number); } else { i = ACTION_RANDOM(sizeof(prefer_steal_models)/sizeof(prefer_steal_models[0])); struct Thing *creatng; creatng = create_creature(pos, prefer_steal_models[i], player->id_number); if (thing_is_invalid(creatng)) return false; SYNCDBG(3,"Created %s owner %d",thing_model_name(creatng),(int)player->id_number); } return true; }
TbBool player_uses_call_to_arms(PlayerNumber plyr_idx) { struct Dungeon *dungeon; dungeon = get_players_num_dungeon(plyr_idx); return (dungeon->cta_start_turn != 0); }
short creature_being_scavenged(struct Thing *creatng) { //return _DK_creature_being_scavenged(creatng); struct Thing *fellowtng; struct Dungeon *dungeon; SYNCDBG(8,"Starting"); //return _DK_make_all_players_creatures_angry(plyr_idx); dungeon = get_players_num_dungeon(creatng->owner); fellowtng = INVALID_THING; if (dungeon->num_active_creatrs <= 1) { SYNCDBG(19,"No other creatures"); return 0; } int n; n = ACTION_RANDOM(dungeon->num_active_creatrs-1); unsigned long k; int i; k = 0; i = dungeon->creatr_list_start; while (i != 0) { struct Thing *thing; thing = thing_get(i); TRACE_THING(thing); struct CreatureControl *cctrl; cctrl = creature_control_get_from_thing(thing); if (thing_is_invalid(thing) || creature_control_invalid(cctrl)) { ERRORLOG("Jump to invalid creature detected"); break; } i = cctrl->players_next_creature_idx; // Thing list loop body if ((n <= 0) && (thing->index != creatng->index)) { fellowtng = thing; break; } n--; // Thing list loop body ends k++; if (k > CREATURES_COUNT) { ERRORLOG("Infinite loop detected when sweeping creatures list"); break; } } if (thing_is_invalid(fellowtng)) { SYNCDBG(19,"Cannot get creature"); return 0; } if (setup_person_move_to_coord(creatng, &fellowtng->mappos, NavRtF_Default) <= 0) { SYNCDBG(19,"Cannot move to coord"); return 0; } creatng->continue_state = CrSt_CreatureBeingScavenged; if (!S3DEmitterIsPlayingSample(creatng->snd_emitter_id, 156, 0)) thing_play_sample(creatng, 156, NORMAL_PITCH, 0, 3, 1, 2, FULL_LOUDNESS); SYNCDBG(19,"Finished"); return 1; }
TbBool player_uses_power_sight(PlayerNumber plyr_idx) { struct Dungeon *dungeon; dungeon = get_players_num_dungeon(plyr_idx); return (dungeon->sight_casted_thing_idx > 0); }