diff --git a/config/creatrs/tunneller.cfg b/config/creatrs/tunneller.cfg index b2bd76578c..945de5c8b4 100644 --- a/config/creatrs/tunneller.cfg +++ b/config/creatrs/tunneller.cfg @@ -30,7 +30,7 @@ DamageToBoulder = 20 ; Creature thing size - XY and Z, one cube is 256x256. ThingSize = 240 400 LairObject = LAIR_TUNLR -Properties = BLEEDS HUMANOID_SKELETON SPECIAL_DIGGER +Properties = BLEEDS HUMANOID_SKELETON DIGGING_CREATURE [attraction] EntranceRoom = NULL NULL NULL diff --git a/src/config_creature.c b/src/config_creature.c index a6ee8246f6..540f953e3b 100644 --- a/src/config_creature.c +++ b/src/config_creature.c @@ -1827,6 +1827,11 @@ TbBool set_creature_available(PlayerNumber plyr_idx, ThingModel crtr_model, long ThingModel get_players_special_digger_model(PlayerNumber plyr_idx) { + struct PlayerInfo* player = get_player(plyr_idx); + + if(player->special_digger != 0) + return player->special_digger; + ThingModel crmodel; if (player_is_roaming(plyr_idx)) @@ -2020,9 +2025,9 @@ CreatureJob get_job_for_subtile(const struct Thing *creatng, MapSubtlCoord stl_x } if (creatng->owner == slabmap_owner(slb)) { - if (thing_is_creature_special_digger(creatng)) + if (thing_is_creature_digger(creatng)) { - if (creatng->model == get_players_special_digger_model(creatng->owner)) + if (creature_is_for_dungeon_diggers_list(creatng)) { required_kind_flags |= JoKF_OwnedDiggers; } @@ -2045,7 +2050,7 @@ CreatureJob get_job_for_subtile(const struct Thing *creatng, MapSubtlCoord stl_x } } else { - if (creatng->model == get_players_special_digger_model(creatng->owner)) { + if (creature_is_for_dungeon_diggers_list(creatng)) { required_kind_flags |= JoKF_EnemyDiggers; } else { required_kind_flags |= JoKF_EnemyCreatures; diff --git a/src/config_creature.h b/src/config_creature.h index 6a0909572c..8a110a1823 100644 --- a/src/config_creature.h +++ b/src/config_creature.h @@ -41,7 +41,7 @@ extern "C" { #define CREATURE_PROPERTY_INCREASE_ON_EXP 35 /******************************************************************************/ enum CreatureModelFlags { - CMF_IsSpecDigger = 0x000001, // Imp and Tunneller. + CMF_IsSpecDigger = 0x000001, // is a dedicated digger that doesn't do things normal units do (like imp) CMF_IsArachnid = 0x000002, // Simply, Spider. CMF_IsDiptera = 0x000004, // Simply, Fly. CMF_IsLordOTLand = 0x000008, // Simply, Knight and Avatar. @@ -61,6 +61,7 @@ enum CreatureModelFlags { CMF_NoTransfer = 0x020000, // Creature cannot be transferred. CMF_Fat = 0x040000, // Creature to fat too walk a full animation. CMF_NoStealHero = 0x080000, // Prevent the creature from being stolen with the Steal Hero special. + CMF_IsDiggingCreature = 0x100000, // unit still counts as a regular creature but can also do digger tasks (like tunneler) }; enum CreatureJobFlags { diff --git a/src/config_crtrmodel.c b/src/config_crtrmodel.c index dad1de1735..5500963504 100644 --- a/src/config_crtrmodel.c +++ b/src/config_crtrmodel.c @@ -120,6 +120,7 @@ const struct NamedCommand creatmodel_properties_commands[] = { {"TREMBLING", 30}, {"FAT", 31}, {"NO_STEAL_HERO", 32}, + {"DIGGING_CREATURE", 33}, {NULL, 0}, }; @@ -769,6 +770,10 @@ TbBool parse_creaturemodel_attributes_blocks(long crtr_model,char *buf,long len, crconf->model_flags |= CMF_NoStealHero; n++; break; + case 33: // DIGGING_CREATURE + crconf->model_flags |= CMF_IsDiggingCreature; + n++; + break; default: CONFWRNLOG("Incorrect value of \"%s\" parameter \"%s\" in [%s] block of %s %s file.", COMMAND_TEXT(cmd_num),word_buf,block_buf, creature_code_name(crtr_model), config_textname); @@ -847,7 +852,7 @@ TbBool parse_creaturemodel_attributes_blocks(long crtr_model,char *buf,long len, } #undef COMMAND_TEXT // If the creature is a special breed, then update an attribute in CreatureConfig struct - if ((crconf->model_flags & CMF_IsSpecDigger) != 0) + if ((crconf->model_flags & (CMF_IsSpecDigger|CMF_IsDiggingCreature)) != 0) { if ((crconf->model_flags & CMF_IsEvil) != 0) { game.conf.crtr_conf.special_digger_evil = crtr_model; @@ -860,7 +865,7 @@ TbBool parse_creaturemodel_attributes_blocks(long crtr_model,char *buf,long len, game.conf.crtr_conf.spectator_breed = crtr_model; } // Set creature start states based on the flags - if ((crconf->model_flags & CMF_IsSpecDigger) != 0) + if ((crconf->model_flags & (CMF_IsSpecDigger|CMF_IsDiggingCreature)) != 0) { crstat->evil_start_state = CrSt_ImpDoingNothing; crstat->good_start_state = CrSt_TunnellerDoingNothing; diff --git a/src/console_cmd.c b/src/console_cmd.c index b6b04e2d39..77821f98a7 100644 --- a/src/console_cmd.c +++ b/src/console_cmd.c @@ -1195,13 +1195,12 @@ TbBool cmd_exec(PlayerNumber plyr_idx, char *msg) PlayerNumber id = get_player_number_for_command(pr2str); player = get_player(plyr_idx); thing = thing_get(player->influenced_thing_idx); - ThingModel model = get_players_special_digger_model(thing->owner); player = get_player(id); if (player_exists(player)) { if (thing_is_creature(thing)) { - if (thing->model == model) + if (creature_is_for_dungeon_diggers_list(thing)) { if (get_random_position_in_dungeon_for_creature(id, CrWaS_WithinDungeon, thing, &pos)) { @@ -1210,6 +1209,7 @@ TbBool cmd_exec(PlayerNumber plyr_idx, char *msg) } } } + //todo replace with any on digger_list thing = find_players_next_creature_of_breed_and_gui_job(get_players_special_digger_model(thing->owner), -1, plyr_idx, TPF_None); if (!thing_is_invalid(thing)) { diff --git a/src/creature_groups.c b/src/creature_groups.c index 2a7e5d3813..030f410ca0 100644 --- a/src/creature_groups.c +++ b/src/creature_groups.c @@ -324,7 +324,7 @@ TbBool remove_creature_from_group_without_leader_consideration(struct Thing *cre static short creature_could_be_lead_digger(struct Thing* creatng, struct CreatureControl* cctrl) { short potential_leader = 0; - if (thing_is_creature_special_digger(creatng)) + if (thing_is_creature_digger(creatng)) { if (cctrl->party_objective != CHeroTsk_DefendParty) { @@ -406,7 +406,7 @@ struct Thing* get_best_creature_to_lead_group(struct Thing* grptng) TRACE_THING(ctng); if (has_digger > 0) { - is_digger = thing_is_creature_special_digger(ctng); + is_digger = thing_is_creature_digger(ctng); } cctrl = creature_control_get_from_thing(ctng); struct CreatureControl* bcctrl = creature_control_get_from_thing(best_creatng); diff --git a/src/creature_jobs.c b/src/creature_jobs.c index 1850362e74..dd0d04aa37 100644 --- a/src/creature_jobs.c +++ b/src/creature_jobs.c @@ -495,7 +495,7 @@ TbBool is_correct_owner_to_perform_job(const struct Thing *creatng, PlayerNumber // We need to check for it later in upper function, because lack of related room may generate message for the player if (creatng->owner == plyr_idx) { - if (creatng->model == get_players_special_digger_model(creatng->owner)) { + if (creature_is_for_dungeon_diggers_list(creatng)) { if ((get_flags_for_job(new_job) & JoKF_OwnedDiggers) == 0) return false; } else { @@ -504,7 +504,7 @@ TbBool is_correct_owner_to_perform_job(const struct Thing *creatng, PlayerNumber } } else { - if (creatng->model == get_players_special_digger_model(creatng->owner)) { + if (creature_is_for_dungeon_diggers_list(creatng)) { if ((get_flags_for_job(new_job) & JoKF_EnemyDiggers) == 0) return false; } else { @@ -992,7 +992,7 @@ TbBool attempt_job_work_in_room_near_pos(struct Thing *creatng, MapSubtlCoord st } creatng->continue_state = get_arrive_at_state_for_job(new_job); cctrl->target_room_id = room->index; - if (thing_is_creature_special_digger(creatng)) + if (thing_is_creature_digger(creatng)) { cctrl->digger.task_repeats = 0; cctrl->job_assigned = new_job; @@ -1017,7 +1017,7 @@ TbBool attempt_job_work_in_room_and_cure_near_pos(struct Thing *creatng, MapSubt creatng->continue_state = get_arrive_at_state_for_job(new_job); cctrl->target_room_id = room->index; process_temple_cure(creatng); - if (thing_is_creature_special_digger(creatng)) + if (thing_is_creature_digger(creatng)) { cctrl->digger.task_repeats = 0; cctrl->job_assigned = new_job; diff --git a/src/creature_states.c b/src/creature_states.c index 9db02ed157..eadf993b0e 100644 --- a/src/creature_states.c +++ b/src/creature_states.c @@ -479,8 +479,8 @@ struct StateInfo states[CREATURE_STATES_COUNT] = { * - 1: Working. * - 2: Fighting. */ -long const state_type_to_gui_state[] = { - 0, 1, 0, 0, 0, 2, 0, 0, 1, 0, 0, 2, 2, 1, 1, 0, +long const state_type_to_gui_state[STATE_TYPES_COUNT] = { + 0, 1, 0, 0, 0, 2, 0, 0, 1, 0, 0, 2, 2, 1, 1, }; /******************************************************************************/ @@ -1508,7 +1508,7 @@ short creature_being_dropped(struct Thing *creatng) if (!creature_affected_by_spell(creatng, SplK_Chicken)) { // Special tasks for diggers - if ((get_creature_model_flags(creatng) & CMF_IsSpecDigger) != 0) + if (thing_is_creature_digger(creatng)) { if ((slabmap_owner(slb) == creatng->owner) || (slabmap_owner(slb) == game.neutral_player_num)) { @@ -3686,7 +3686,7 @@ CrCheckRet move_check_persuade(struct Thing *creatng) !thing_is_invalid(i); i = thing_get(i->next_on_mapblk) ) { - if (i->owner != creatng->owner || !thing_is_creature(i) || i == creatng || i->model == get_players_special_digger_model(creatng->owner)) + if (i->owner != creatng->owner || !thing_is_creature(i) || i == creatng || creature_is_for_dungeon_diggers_list(i)) continue; i_leader = get_group_leader(i); if (i_leader) @@ -4767,7 +4767,7 @@ short set_start_state_f(struct Thing *thing,const char *func_name) if (player->victory_state == VicS_LostLevel) { // TODO: Correctly deal with possession of creatures not owned by the player - if (thing->model != get_players_special_digger_model(player->id_number)) + if (!creature_is_for_dungeon_diggers_list(thing)) { cleanup_current_thing_state(thing); initialise_thing_state(thing, CrSt_LeavesBecauseOwnerLost); diff --git a/src/creature_states.h b/src/creature_states.h index c1b830b57d..9aed424a08 100644 --- a/src/creature_states.h +++ b/src/creature_states.h @@ -21,12 +21,12 @@ #include "bflib_basics.h" #include "globals.h" -#include "dungeon_data.h" /** Count of creature states, originally 147. */ #define CREATURE_STATES_COUNT CrSt_ListEnd #define FIGHT_FEAR_DELAY 160 +#define STATE_TYPES_COUNT CrStTyp_ListEnd #ifdef __cplusplus extern "C" { diff --git a/src/creature_states_combt.c b/src/creature_states_combt.c index 6dc8f8a95b..b7beed2f2b 100644 --- a/src/creature_states_combt.c +++ b/src/creature_states_combt.c @@ -130,7 +130,7 @@ TbBool creature_is_being_attacked_by_enemy_creature_not_digger(struct Thing *fig for (oppn_idx = 0; oppn_idx < COMBAT_MELEE_OPPONENTS_LIMIT; oppn_idx++) { struct Thing* enmtng = thing_get(figctrl->opponents_melee[oppn_idx]); - if (!thing_is_invalid(enmtng) && !thing_is_creature_special_digger(enmtng)) + if (!thing_is_invalid(enmtng) && !thing_is_creature_digger(enmtng)) { if (players_are_enemies(fightng->owner,enmtng->owner)) { return true; @@ -141,7 +141,7 @@ TbBool creature_is_being_attacked_by_enemy_creature_not_digger(struct Thing *fig for (oppn_idx = 0; oppn_idx < COMBAT_RANGED_OPPONENTS_LIMIT; oppn_idx++) { struct Thing* enmtng = thing_get(figctrl->opponents_ranged[oppn_idx]); - if (!thing_is_invalid(enmtng) && !thing_is_creature_special_digger(enmtng)) + if (!thing_is_invalid(enmtng) && !thing_is_creature_digger(enmtng)) { if (players_are_enemies(fightng->owner,enmtng->owner)) { return true; diff --git a/src/creature_states_spdig.c b/src/creature_states_spdig.c index f7f400d13c..856c7a4c13 100644 --- a/src/creature_states_spdig.c +++ b/src/creature_states_spdig.c @@ -1020,7 +1020,7 @@ short imp_birth(struct Thing *thing) { // If the creature has flight ability, make sure it returns to flying state restore_creature_flight_flag(thing); - if (thing_is_creature_special_digger(thing)) + if (thing_is_creature_digger(thing)) { if (!check_out_available_spdigger_drop_tasks(thing)) { set_start_state(thing); @@ -1201,7 +1201,7 @@ short imp_doing_nothing(struct Thing *spdigtng) { SYNCDBG(19,"Starting for %s index %d",thing_model_name(spdigtng),(int)spdigtng->index); TRACE_THING(spdigtng); - if (!thing_is_creature_special_digger(spdigtng)) + if (!thing_is_creature_digger(spdigtng)) { ERRORLOG("Non digger thing %ld, %s, owner %ld - reset",(long)spdigtng->index,thing_model_name(spdigtng),(long)spdigtng->owner); set_start_state(spdigtng); diff --git a/src/dungeon_data.h b/src/dungeon_data.h index d300facad8..26ec7d435c 100644 --- a/src/dungeon_data.h +++ b/src/dungeon_data.h @@ -36,6 +36,8 @@ #include "thing_traps.h" #include "roomspace.h" #include "config_creature.h" +#include "creature_states.h" + #include "power_hand.h" #ifdef __cplusplus @@ -154,7 +156,7 @@ struct Dungeon { unsigned short num_summon; ThingIndex things_in_hand[MAX_THINGS_IN_HAND]; unsigned char num_things_in_hand; - unsigned short field_64[CREATURE_TYPES_MAX][15]; + unsigned short crmodel_state_type_count[CREATURE_TYPES_MAX][STATE_TYPES_COUNT]; unsigned short guijob_all_creatrs_count[CREATURE_TYPES_MAX][3]; unsigned short guijob_angry_creatrs_count[CREATURE_TYPES_MAX][3]; int sight_casted_gameturn; diff --git a/src/frontmenu_ingame_tabs.c b/src/frontmenu_ingame_tabs.c index ea60546904..853aab7dbf 100644 --- a/src/frontmenu_ingame_tabs.c +++ b/src/frontmenu_ingame_tabs.c @@ -1759,29 +1759,29 @@ void gui_activity_background(struct GuiMenu *gmnu) activity_list[4*i+0] = 0; activity_list[4*i+1] = 0; activity_list[4*i+2] = 0; - for (int n = 0; n < 15; n++) + for (int n = 0; n < STATE_TYPES_COUNT; n++) { - int job_idx = state_type_to_gui_state[n]; - switch (job_idx) + int gui_state_idx = state_type_to_gui_state[n]; + switch (gui_state_idx) { - case 0: - activity_list[4*i+0] += dungeon->field_64[crmodel][n]; + case CrGUIJob_Wandering: + activity_list[4*i+0] += dungeon->crmodel_state_type_count[crmodel][n]; break; - case 1: - activity_list[4*i+1] += dungeon->field_64[crmodel][n]; + case CrGUIJob_Working: + activity_list[4*i+1] += dungeon->crmodel_state_type_count[crmodel][n]; break; - case 2: - activity_list[4*i+2] += dungeon->field_64[crmodel][n]; + case CrGUIJob_Fighting: + activity_list[4*i+2] += dungeon->crmodel_state_type_count[crmodel][n]; break; default: - ERRORLOG("Outranged GUI state value %d",(int)job_idx); + ERRORLOG("Outranged GUI state value %d",(int)gui_state_idx); break; } } } - int mm_units_per_px = (gmnu->width * 16 + 140 / 2) / 140; lbDisplay.DrawFlags |= Lb_SPRITE_TRANSPAR4; - LbDrawBox(gmnu->pos_x + scale_value_for_resolution_with_upp(2, mm_units_per_px), gmnu->pos_y + scale_value_for_resolution_with_upp(218, mm_units_per_px), scale_value_for_resolution_with_upp(134, mm_units_per_px), scale_value_for_resolution_with_upp(24, mm_units_per_px), colours[0][0][0]); + LbDrawBox(gmnu->pos_x + scale_ui_value(2),gmnu->pos_y + scale_ui_value(218),scale_ui_value(134),scale_ui_value(24),colours[0][0][0]); + lbDisplay.DrawFlags = flg_mem; } diff --git a/src/lvl_script_commands.c b/src/lvl_script_commands.c index 3aa61276ed..03b72a5387 100644 --- a/src/lvl_script_commands.c +++ b/src/lvl_script_commands.c @@ -543,7 +543,7 @@ TbBool script_change_creatures_annoyance(PlayerNumber plyr_idx, ThingModel crmod struct Dungeon* dungeon = get_players_num_dungeon(plyr_idx); unsigned long k = 0; int i = dungeon->creatr_list_start; - if ((crmodel == get_players_special_digger_model(plyr_idx)) || (crmodel == CREATURE_DIGGER)) + if (creature_kind_is_for_dungeon_diggers_list(plyr_idx,crmodel)) { i = dungeon->digger_list_start; } @@ -2046,22 +2046,22 @@ static void set_hand_rule_process(struct ScriptContext* context) long param = context->value->shorts[4]; long crtr_id_start = ((crtr_id == CREATURE_ANY) || (crtr_id == CREATURE_NOT_A_DIGGER)) ? 0 : crtr_id; long crtr_id_end = ((crtr_id == CREATURE_ANY) || (crtr_id == CREATURE_NOT_A_DIGGER)) ? CREATURE_TYPES_MAX : crtr_id + 1; - ThingModel digger_model; struct Dungeon* dungeon; - for (int i = context->plr_start; i < context->plr_end; i++) + for (int plyr_idx = context->plr_start; plyr_idx < context->plr_end; plyr_idx++) { - digger_model = get_players_special_digger_model(i); for (int ci = crtr_id_start; ci < crtr_id_end; ci++) { + + //todo maybe should use creature_model_matches_model somewhere? if (crtr_id == CREATURE_NOT_A_DIGGER) { - if (ci == digger_model) + if (creature_kind_is_for_dungeon_diggers_list(plyr_idx,ci)) { continue; } } - dungeon = get_dungeon(i); + dungeon = get_dungeon(plyr_idx); if (hand_rule_action == HandRuleAction_Allow || hand_rule_action == HandRuleAction_Deny) { dungeon->hand_rules[ci][hand_rule_slot].enabled = 1; @@ -6459,12 +6459,6 @@ static void swap_creature_check(const struct ScriptLine* scline) ThingModel ncrt_id = scline->np[0]; ThingModel crtr_id = scline->np[1]; - struct CreatureModelConfig* crconf = &game.conf.crtr_conf.model[crtr_id]; - if ((crconf->model_flags & CMF_IsSpecDigger) != 0) - { - SCRPTERRLOG("Unable to swap special diggers"); - DEALLOCATE_SCRIPT_VALUE; - } value->shorts[0] = ncrt_id; value->shorts[1] = crtr_id; PROCESS_SCRIPT_VALUE(scline->command); @@ -6479,6 +6473,46 @@ static void swap_creature_process(struct ScriptContext* context) { SCRPTERRLOG("Error swapping creatures '%s'<->'%s'", creature_code_name(ncrt_id), creature_code_name(crtr_id)); } + recalculate_all_creature_digger_lists(); +} + +static void set_digger_check(const struct ScriptLine* scline) +{ + ALLOCATE_SCRIPT_VALUE(scline->command, scline->np[0]); + ThingModel crtr_id = get_rid(creature_desc, scline->tp[1]); + + if (crtr_id == -1) + { + SCRPTERRLOG("Unknown creature, '%s'", scline->tp[1]); + return; + } + + value->shorts[0] = crtr_id; + PROCESS_SCRIPT_VALUE(scline->command); +} + +static void set_digger_process(struct ScriptContext* context) +{ + ThingModel new_dig_model = context->value->shorts[0]; + for (int plyr_idx = context->plr_start; plyr_idx < context->plr_end; plyr_idx++) + { + ThingModel old_dig_model = get_players_special_digger_model(plyr_idx); + if (old_dig_model == new_dig_model) + { + continue; + } + struct PlayerInfo* player = get_player(plyr_idx); + + player->special_digger = context->value->shorts[0]; + + for (size_t i = 0; i < CREATURE_TYPES_MAX; i++) + { + if (breed_activities[i] == old_dig_model) + breed_activities[i] = new_dig_model; + else if (breed_activities[i] == new_dig_model) + breed_activities[i] = old_dig_model; + } + } } /** @@ -6639,6 +6673,7 @@ const struct CommandDesc command_desc[] = { {"ADD_TO_PLAYER_MODIFIER", "PAN ", Cmd_ADD_TO_PLAYER_MODIFIER, &add_to_player_modifier_check, &add_to_player_modifier_process}, {"CHANGE_SLAB_TEXTURE", "NNAa ", Cmd_CHANGE_SLAB_TEXTURE , &change_slab_texture_check, &change_slab_texture_process}, {"ADD_OBJECT_TO_LEVEL_AT_POS", "ANNNp ", Cmd_ADD_OBJECT_TO_LEVEL_AT_POS, &add_object_to_level_at_pos_check, &add_object_to_level_at_pos_process}, + {"SET_DIGGER", "PC ", Cmd_SET_DIGGER , &set_digger_check, &set_digger_process}, {NULL, " ", Cmd_NONE, NULL, NULL}, }; diff --git a/src/lvl_script_lib.h b/src/lvl_script_lib.h index b208765127..28879f03ba 100644 --- a/src/lvl_script_lib.h +++ b/src/lvl_script_lib.h @@ -187,6 +187,7 @@ enum TbScriptCommands { Cmd_CHANGE_SLAB_TEXTURE = 174, Cmd_MOVE_PLAYER_CAMERA_TO = 175, Cmd_ADD_OBJECT_TO_LEVEL_AT_POS = 176, + Cmd_SET_DIGGER = 177, }; struct ScriptLine { diff --git a/src/lvl_script_value.c b/src/lvl_script_value.c index 4fbc3dbe7e..f3e2d451fb 100644 --- a/src/lvl_script_value.c +++ b/src/lvl_script_value.c @@ -593,6 +593,7 @@ void script_process_value(unsigned long var_index, unsigned long plr_range_id, l { clear_flag(crconf->model_flags,CMF_IsSpecDigger); } + recalculate_all_creature_digger_lists(); break; case 11: // ARACHNID if (val4 >= 1) diff --git a/src/main.cpp b/src/main.cpp index cdc1cbb1ae..cac1e16484 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2555,7 +2555,7 @@ int clear_active_dungeons_stats(void) dungeon = get_dungeon(i); if (dungeon_invalid(dungeon)) break; - memset((char *)dungeon->field_64, 0, game.conf.crtr_conf.model_count * 15 * sizeof(unsigned short)); + memset((char *)dungeon->crmodel_state_type_count, 0, game.conf.crtr_conf.model_count * STATE_TYPES_COUNT * sizeof(unsigned short)); memset((char *)dungeon->guijob_all_creatrs_count, 0, game.conf.crtr_conf.model_count *3*sizeof(unsigned short)); memset((char *)dungeon->guijob_angry_creatrs_count, 0, game.conf.crtr_conf.model_count *3*sizeof(unsigned short)); } diff --git a/src/packets_input.c b/src/packets_input.c index af1ba6496a..aae114aeb6 100644 --- a/src/packets_input.c +++ b/src/packets_input.c @@ -223,14 +223,14 @@ TbBool process_dungeon_power_hand_state(long plyr_idx) if (player->hand_thing_idx == 0) { create_power_hand(player->id_number); } - long i = thing_is_creature_special_digger(thing); - if ((can_drop_thing_here(stl_x, stl_y, player->id_number, i) + long is_digger = thing_is_creature_digger(thing); + if ((can_drop_thing_here(stl_x, stl_y, player->id_number, is_digger) || !can_dig_here(stl_x, stl_y, player->id_number, true)) && (!player->one_click_lock_cursor)) { player->render_roomspace = create_box_roomspace(player->render_roomspace, 1, 1, subtile_slab(stl_x), subtile_slab(stl_y)); player->full_slab_cursor = (player->roomspace_mode != single_subtile_mode); - tag_cursor_blocks_thing_in_hand(plyr_idx, stl_x, stl_y, i, player->full_slab_cursor); + tag_cursor_blocks_thing_in_hand(plyr_idx, stl_x, stl_y, is_digger, player->full_slab_cursor); } else { player->additional_flags |= PlaAF_ChosenSubTileIsHigh; diff --git a/src/player_compevents.c b/src/player_compevents.c index 8b2c71b125..b473f64d84 100644 --- a/src/player_compevents.c +++ b/src/player_compevents.c @@ -422,7 +422,7 @@ PowerKind computer_choose_attack_spell(struct Computer2 *comp, struct ComputerEv } // Only cast lightning on imps, don't waste expensive chicken or disease spells - if ((thing_is_creature_special_digger(creatng)) && (caspl->pwkind != PwrK_LIGHTNING)) + if ((thing_is_creature_digger(creatng)) && (caspl->pwkind != PwrK_LIGHTNING)) { i++; continue; diff --git a/src/player_data.h b/src/player_data.h index 43003c1700..3eb31f75d8 100644 --- a/src/player_data.h +++ b/src/player_data.h @@ -265,6 +265,7 @@ short cursor_light_idx; TbBool roomspace_horizontal_first; TbBool pickup_all_gold; unsigned char player_type; //enum PlayerTypes + ThingModel special_digger; int isometric_tilt; }; diff --git a/src/power_hand.c b/src/power_hand.c index 62c6df1874..613e7b2331 100644 --- a/src/power_hand.c +++ b/src/power_hand.c @@ -960,7 +960,7 @@ short dump_first_held_thing_on_map(PlayerNumber plyr_idx, MapSubtlCoord stl_x, M } // Check if drop position is allowed struct Thing *droptng = thing_get(dungeon->things_in_hand[0]); - if (!can_drop_thing_here(stl_x, stl_y, plyr_idx, thing_is_creature_special_digger(droptng))) { + if (!can_drop_thing_here(stl_x, stl_y, plyr_idx, thing_is_creature_digger(droptng))) { // Make a rejection sound if (is_my_player_number(plyr_idx)) { @@ -1490,7 +1490,7 @@ short can_place_thing_here(struct Thing *thing, long stl_x, long stl_y, long dng { struct Coord3d pos; TbBool is_digger; - is_digger = thing_is_creature_special_digger(thing); + is_digger = thing_is_creature_digger(thing); if (!can_drop_thing_here(stl_x, stl_y, dngn_idx, is_digger)) return false; pos.x.val = subtile_coord_center(stl_x); diff --git a/src/room_jobs.c b/src/room_jobs.c index 277fcafdf4..6a18e93443 100644 --- a/src/room_jobs.c +++ b/src/room_jobs.c @@ -391,7 +391,7 @@ TbBool room_is_correct_to_perform_job(const struct Thing *creatng, const struct } if (creatng->owner == room->owner) { - if (creatng->model == get_players_special_digger_model(creatng->owner)) { + if (creature_is_for_dungeon_diggers_list(creatng)) { if ((get_flags_for_job(jobpref) & JoKF_OwnedDiggers) == 0) return false; } else { @@ -400,7 +400,7 @@ TbBool room_is_correct_to_perform_job(const struct Thing *creatng, const struct } } else { - if (creatng->model == get_players_special_digger_model(creatng->owner)) { + if (creature_is_for_dungeon_diggers_list(creatng)) { if ((get_flags_for_job(jobpref) & JoKF_EnemyDiggers) == 0) return false; } else { diff --git a/src/thing_creature.c b/src/thing_creature.c index 6ab668fdba..945a96947f 100644 --- a/src/thing_creature.c +++ b/src/thing_creature.c @@ -149,24 +149,20 @@ TbBool thing_can_be_controlled_as_passenger(struct Thing *thing) TbBool creature_is_for_dungeon_diggers_list(const struct Thing *creatng) { - //TODO DIGGERS For now, only player-specific and non-hero special diggers are on the diggers list - if (is_hero_thing(creatng)) - return false; - return (creatng->model == get_players_special_digger_model(creatng->owner)); - //struct CreatureModelConfig *crconf; - //crconf = &game.conf.crtr_conf.model[creatng->model]; - //return ((crconf->model_flags & CMF_IsSpecDigger) != 0); + return creature_kind_is_for_dungeon_diggers_list(creatng->owner,creatng->model); } TbBool creature_kind_is_for_dungeon_diggers_list(PlayerNumber plyr_idx, ThingModel crmodel) { - //TODO DIGGERS For now, only player-specific and non-hero special diggers are on the diggers list if (player_is_roaming(plyr_idx)) return false; - return (crmodel == get_players_special_digger_model(plyr_idx)); - //struct CreatureModelConfig *crconf; - //crconf = &game.conf.crtr_conf.model[crmodel]; - //is_spec_digger = ((crconf->model_flags & CMF_IsSpecDigger) != 0); + + if (crmodel == CREATURE_DIGGER) + return true; + + struct CreatureModelConfig *crconf; + crconf = &game.conf.crtr_conf.model[crmodel]; + return flag_is_set(crconf->model_flags,CMF_IsSpecDigger); } /** @@ -1868,7 +1864,7 @@ void update_creature_count(struct Thing *creatng) return; } int statyp = get_creature_state_type(creatng); - dungeon->field_64[creatng->model][statyp]++; + dungeon->crmodel_state_type_count[creatng->model][statyp]++; int job_idx = get_creature_gui_job(creatng); if (can_thing_be_picked_up_by_player(creatng, creatng->owner)) { @@ -2086,7 +2082,7 @@ TngUpdateRet process_creature_state(struct Thing *thing) } // Creatures that are not special diggers will pick up any nearby gold or food - if (((thing->movement_flags & TMvF_Flying) == 0) && ((model_flags & CMF_IsSpecDigger) == 0)) + if (((thing->movement_flags & TMvF_Flying) == 0) && ((model_flags & (CMF_IsSpecDigger|CMF_IsDiggingCreature)) == 0)) { if (!creature_is_being_unconscious(thing) && !creature_is_dying(thing) && !thing_is_picked_up(thing) && !creature_is_being_dropped(thing)) @@ -3971,6 +3967,14 @@ void set_first_creature(struct Thing *creatng) } } +void recalculate_all_creature_digger_lists() +{ + for (PlayerNumber plyr_idx = 0; plyr_idx < PLAYERS_COUNT; plyr_idx++) + { + recalculate_player_creature_digger_lists(plyr_idx); + } +} + void recalculate_player_creature_digger_lists(PlayerNumber plr_idx) { ThingIndex previous_digger = 0; @@ -4139,11 +4143,11 @@ TbBool thing_is_dead_creature(const struct Thing *thing) * @param thing The thing to be checked. * @return True if the thing is creature and special digger, false otherwise. */ -TbBool thing_is_creature_special_digger(const struct Thing *thing) +TbBool thing_is_creature_digger(const struct Thing *thing) { if (!thing_is_creature(thing)) return false; - return ((get_creature_model_flags(thing) & CMF_IsSpecDigger) != 0); + return ((get_creature_model_flags(thing) & (CMF_IsSpecDigger|CMF_IsDiggingCreature)) != 0); } /** Returns if a thing the creature type set as spectator, normally the floating spirit. @@ -5845,10 +5849,7 @@ long update_creature_levels(struct Thing *thing) continue; } struct CreatureModelConfig* crconf = &game.conf.crtr_conf.model[model]; - if ((crconf->model_flags & CMF_IsSpectator) != 0) { - continue; - } - if ((crconf->model_flags & CMF_IsSpecDigger) != 0) { + if ((crconf->model_flags & (CMF_IsSpectator|CMF_IsSpecDigger|CMF_IsDiggingCreature)) != 0) { continue; } diff --git a/src/thing_creature.h b/src/thing_creature.h index 3011e313a3..deae214337 100644 --- a/src/thing_creature.h +++ b/src/thing_creature.h @@ -144,6 +144,7 @@ void set_first_creature(struct Thing *thing); void remove_first_creature(struct Thing *thing); long player_list_creature_filter_needs_to_be_placed_in_room_for_job(const struct Thing *thing, MaxTngFilterParam param, long maximizer); void recalculate_player_creature_digger_lists(PlayerNumber plr_idx); +void recalculate_all_creature_digger_lists(); TbBool creature_has_lair_room(const struct Thing *creatng); struct Room *get_creature_lair_room(const struct Thing *creatng); @@ -206,7 +207,7 @@ TbBool creature_can_be_queried(struct PlayerInfo *player, struct Thing *creatng) /******************************************************************************/ TbBool thing_is_creature(const struct Thing *thing); TbBool thing_is_dead_creature(const struct Thing *thing); -TbBool thing_is_creature_special_digger(const struct Thing *thing); +TbBool thing_is_creature_digger(const struct Thing *thing); TbBool thing_is_creature_spectator(const struct Thing *thing); TbBool creature_is_slappable(const struct Thing *thing, PlayerNumber plyr_idx); TbBool creature_is_invisible(const struct Thing *thing); diff --git a/src/thing_list.c b/src/thing_list.c index 1a7d29d212..5ec507c54f 100644 --- a/src/thing_list.c +++ b/src/thing_list.c @@ -219,31 +219,6 @@ void add_thing_to_its_class_list(struct Thing *thing) add_thing_to_list(thing, slist); } -/** - * Filter function. - * @param thing The thing being checked. - * @param param Parameters exchanged between filter calls. - * @param maximizer Previous value which made a thing pass the filter. - */ -long near_map_block_thing_filter_not_specdigger(const struct Thing *thing, MaxTngFilterParam param, long maximizer) -{ - if (thing->class_id == TCls_Creature) - { - if ((get_creature_model_flags(thing) & CMF_IsSpecDigger) == 0) - { - // Prepare reference Coord3d struct for distance computation - struct Coord3d refpos; - refpos.x.val = param->num1; - refpos.y.val = param->num2; - refpos.z.val = 0; - // This function should return max value when the distance is minimal, so: - return LONG_MAX-get_2d_distance(&thing->mappos, &refpos); - } - } - // If conditions are not met, return -1 to be sure thing will not be returned. - return -1; -} - /** * Filter function. * @param thing The thing being checked. @@ -433,7 +408,7 @@ long near_map_block_thing_filter_is_enemy_of_able_to_attack_and_not_specdigger(c { if (!creature_is_being_unconscious(thing) && !thing_is_picked_up(thing) && !creature_is_kept_in_custody_by_enemy(thing) && !creature_is_leaving_and_cannot_be_stopped(thing)) { - if ((get_creature_model_flags(thing) & CMF_IsSpecDigger) == 0) + if ((get_creature_model_flags(thing) & (CMF_IsSpecDigger|CMF_IsDiggingCreature)) == 0) { // Prepare reference Coord3d struct for distance computation struct Coord3d refpos; @@ -566,14 +541,6 @@ long near_map_block_thing_filter_can_be_keeper_power_target(const struct Thing * return -1; } -/** Deprecated filter function. */ -long creature_near_filter_is_enemy_of_and_not_specdigger(const struct Thing *thing, FilterParam plyr_idx) -{ - if (thing->owner == plyr_idx) - return false; - return ((get_creature_model_flags(thing) & CMF_IsSpecDigger) == 0); -} - long creature_near_filter_is_owned_by(const struct Thing *thing, FilterParam plyr_idx) { if (thing->owner == plyr_idx) @@ -3757,24 +3724,6 @@ struct Thing* get_player_creature_in_range_around_own_heart(PlayerNumber plyr_id return INVALID_THING; } -/** Finds creature on revealed subtiles around given position, who is not special digger. - * - * @param pos_x Position to search around X coord. - * @param pos_y Position to search around Y coord. - * @param plyr_idx Player whose revealed subtiles around will be searched. - * @return The creature thing pointer, or invalid thing pointer if not found. - */ -struct Thing *get_creature_near_but_not_specdigger(MapCoord pos_x, MapCoord pos_y, PlayerNumber plyr_idx) -{ - SYNCDBG(19,"Starting"); - Thing_Maximizer_Filter filter = near_map_block_thing_filter_not_specdigger; - struct CompoundTngFilterParam param; - param.plyr_idx = plyr_idx; - param.num1 = pos_x; - param.num2 = pos_y; - return get_thing_near_revealed_map_block_with_filter(pos_x, pos_y, filter, ¶m); -} - /** Finds thing on revealed subtiles around given position, which matches given bool filter. * * @param pos_x Position to search around X coord. @@ -3796,25 +3745,6 @@ struct Thing *get_object_around_owned_by_and_matching_bool_filter(MapCoord pos_x return get_thing_spiral_near_map_block_with_filter(pos_x, pos_y, 9, filter, ¶m); } -/** Finds creature on revealed subtiles around given position, who is not special digger and is enemy to given player. - * - * @param pos_x Position to search around X coord. - * @param pos_y Position to search around Y coord. - * @param plyr_idx Player whose revealed subtiles around will be searched. - * @return The creature thing pointer, or invalid thing pointer if not found. - */ -struct Thing *get_creature_near_who_is_enemy_of_and_not_specdigger(MapCoord pos_x, MapCoord pos_y, PlayerNumber plyr_idx) -{ - SYNCDBG(19,"Starting"); - //return get_creature_near_with_filter(x, y, creature_near_filter_is_enemy_of_and_not_specdigger, plyr_idx); - Thing_Maximizer_Filter filter = near_map_block_thing_filter_is_enemy_of_able_to_attack_and_not_specdigger; - struct CompoundTngFilterParam param; - param.plyr_idx = plyr_idx; - param.num1 = pos_x; - param.num2 = pos_y; - return get_thing_near_revealed_map_block_with_filter(pos_x, pos_y, filter, ¶m); -} - /** Finds creature on subtiles in range around given position, who is not special digger and is enemy to given player, able to attack. * * @param pos_x Position to search around X coord. @@ -3826,7 +3756,6 @@ struct Thing *get_creature_near_who_is_enemy_of_and_not_specdigger(MapCoord pos_ struct Thing *get_creature_in_range_who_is_enemy_of_able_to_attack_and_not_specdigger(MapCoord pos_x, MapCoord pos_y, long distance_stl, PlayerNumber plyr_idx) { SYNCDBG(19,"Starting"); - //return get_creature_near_with_filter(x, y, creature_near_filter_is_enemy_of_and_not_specdigger, plyr_idx); Thing_Maximizer_Filter filter = near_map_block_thing_filter_is_enemy_of_able_to_attack_and_not_specdigger; struct CompoundTngFilterParam param; param.plyr_idx = plyr_idx; diff --git a/src/thing_list.h b/src/thing_list.h index c825d6c158..d92a4b2b2f 100644 --- a/src/thing_list.h +++ b/src/thing_list.h @@ -194,7 +194,6 @@ void add_thing_to_its_class_list(struct Thing *thing); ThingIndex get_thing_class_list_head(ThingClass class_id); struct StructureList *get_list_for_thing_class(ThingClass class_id); -long creature_near_filter_is_enemy_of_and_not_specdigger(const struct Thing *thing, FilterParam val); long creature_near_filter_is_owned_by(const struct Thing *thing, FilterParam val); // Filters to select creature anywhere on map but belonging to given player @@ -231,8 +230,6 @@ long do_to_things_with_param_spiral_near_map_block(const struct Coord3d *center_ long do_to_things_with_param_around_map_block(const struct Coord3d *center_pos, Thing_Modifier_Func do_cb, ModTngFilterParam param); long near_map_block_creature_filter_diagonal_random(const struct Thing* thing, MaxTngFilterParam param, long maximizer); // Final routines to select thing on/near given map position -struct Thing *get_creature_near_but_not_specdigger(MapCoord pos_x, MapCoord pos_y, PlayerNumber plyr_idx); -struct Thing *get_creature_near_who_is_enemy_of_and_not_specdigger(MapCoord pos_x, MapCoord pos_y, PlayerNumber plyr_idx); struct Thing *get_creature_near_to_be_keeper_power_target(MapCoord pos_x, MapCoord pos_y, PowerKind pwmodel, PlayerNumber plyr_idx); struct Thing *get_nearest_thing_for_slap(PlayerNumber plyr_idx, MapCoord pos_x, MapCoord pos_y); struct Thing *get_creature_near_and_owned_by(MapCoord pos_x, MapCoord pos_y, PlayerNumber plyr_idx, long crmodel);