Skip to content

Commit

Permalink
Extra ADD_CREATURE_TO_LEVEL param to determine spawn method (#3841)
Browse files Browse the repository at this point in the history
  • Loading branch information
Loobinex authored Jan 24, 2025
1 parent a388650 commit c56493d
Show file tree
Hide file tree
Showing 13 changed files with 115 additions and 61 deletions.
15 changes: 15 additions & 0 deletions src/config_creature.c
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,21 @@ const struct NamedCommand instance_range_desc[] = {
{NULL, -1},
};

const struct NamedCommand spawn_type_desc[] = {
{"NONE", SpwnT_None },
{"0", SpwnT_None },
{"DEFAULT", SpwnT_Default },
{"1", SpwnT_Default },
{"JUMP", SpwnT_Jump },
{"2", SpwnT_Jump },
{"FALL", SpwnT_Fall },
{"3", SpwnT_Fall },
{"INIT", SpwnT_Initialize },
{"INITIALIZE", SpwnT_Initialize },
{"4", SpwnT_Initialize },
{NULL, -1 },
};

/******************************************************************************/
struct NamedCommand creature_desc[CREATURE_TYPES_MAX];
struct NamedCommand instance_desc[INSTANCE_TYPES_MAX];
Expand Down
9 changes: 9 additions & 0 deletions src/config_creature.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,14 @@ enum CreatureAttackType {
AttckT_Ranged,
};

enum CreatureSpawnType {
SpwnT_None = 0,
SpwnT_Default,
SpwnT_Jump,
SpwnT_Fall,
SpwnT_Initialize
};

/******************************************************************************/
#pragma pack(1)

Expand Down Expand Up @@ -278,6 +286,7 @@ extern const struct NamedCommand creatmodel_experience_commands[];
extern const struct NamedCommand creatmodel_senses_commands[];
extern const struct NamedCommand creatmodel_appearance_commands[];
extern const struct NamedCommand creature_deathkind_desc[];
extern const struct NamedCommand spawn_type_desc[];
extern Creature_Job_Player_Check_Func creature_job_player_check_func_list[];
/******************************************************************************/
struct CreatureStats *creature_stats_get(ThingModel crstat_idx);
Expand Down
2 changes: 1 addition & 1 deletion src/creature_groups.c
Original file line number Diff line number Diff line change
Expand Up @@ -903,7 +903,7 @@ struct Thing *script_process_new_party(struct Party *party, PlayerNumber plyr_id
break;
}
struct PartyMember* member = &(party->members[k]);
struct Thing* thing = script_create_new_creature(plyr_idx, member->crtr_kind, location, member->carried_gold, member->crtr_level);
struct Thing* thing = script_create_new_creature(plyr_idx, member->crtr_kind, location, member->carried_gold, member->crtr_level, SpwnT_Default);
if (!thing_is_invalid(thing))
{
struct CreatureControl* cctrl = creature_control_get_from_thing(thing);
Expand Down
2 changes: 1 addition & 1 deletion src/creature_states_hero.c
Original file line number Diff line number Diff line change
Expand Up @@ -1302,7 +1302,7 @@ TbBool script_support_send_tunneller_to_appropriate_dungeon(struct Thing *creatn
struct Thing *script_process_new_tunneler(unsigned char plyr_idx, TbMapLocation location, TbMapLocation heading, unsigned char crtr_level, unsigned long carried_gold)
{
ThingModel diggerkind = get_players_special_digger_model(plyr_idx);
struct Thing* creatng = script_create_creature_at_location(plyr_idx, diggerkind, location);
struct Thing* creatng = script_create_creature_at_location(plyr_idx, diggerkind, location, SpwnT_Default);
if (thing_is_invalid(creatng))
return INVALID_THING;
creatng->creature.gold_carried = carried_gold;
Expand Down
10 changes: 5 additions & 5 deletions src/keeperfx.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ void draw_gold_total(PlayerNumber plyr_idx, long scr_x, long scr_y, long units_p
void draw_mini_things_in_hand(long x, long y);
TbBool screen_to_map(struct Camera *camera, long screen_x, long screen_y, struct Coord3d *mappos);
void update_creatr_model_activities_list(void);
void find_map_location_coords(long location, long *x, long *y, int plyr_idx, const char *func_name);
void find_map_location_coords(TbMapLocation location, long *x, long *y, int plyr_idx, const char *func_name);
TbBool any_player_close_enough_to_see(const struct Coord3d *pos);
void affect_nearby_stuff_with_vortex(struct Thing *thing);
void affect_nearby_friends_with_alarm(struct Thing *thing);
Expand All @@ -282,10 +282,10 @@ short winning_player_quitting(struct PlayerInfo *player, long *plyr_count);
short lose_level(struct PlayerInfo *player);
short resign_level(struct PlayerInfo *player);
short complete_level(struct PlayerInfo *player);
void set_general_information(long msg_id, long target, long x, long y);
void set_quick_information(long msg_id, long target, long x, long y);
void process_objective(const char *msg_text, long target, long x, long y);
void set_general_objective(long msg_id, long target, long x, long y);
void set_general_information(long msg_id, TbMapLocation target, long x, long y);
void set_quick_information(long msg_id, TbMapLocation target, long x, long y);
void process_objective(const char *msg_text, TbMapLocation target, long x, long y);
void set_general_objective(long msg_id, TbMapLocation target, long x, long y);
void turn_off_power_sight_of_evil(PlayerNumber plridx);
void turn_off_power_obey(PlayerNumber plyr_idx);

Expand Down
3 changes: 1 addition & 2 deletions src/lvl_script.c
Original file line number Diff line number Diff line change
Expand Up @@ -1253,8 +1253,7 @@ static void process_party(struct PartyTrigger* pr_trig)
break;
case TrgF_CREATE_CREATURE:
SCRIPTDBG(6, "Adding creature %ld", n);
script_process_new_creatures(pr_trig->plyr_idx, n, pr_trig->location,
pr_trig->ncopies, pr_trig->carried_gold, pr_trig->crtr_level);
script_process_new_creatures(pr_trig->plyr_idx, n, pr_trig->location, pr_trig->ncopies, pr_trig->carried_gold, pr_trig->crtr_level, pr_trig->spawn_type);
break;
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/lvl_script.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,10 @@ struct PartyTrigger {
};
union
{
unsigned long location;
TbMapLocation location;
unsigned long countdown;
};
char spawn_type;
unsigned char crtr_level;
unsigned short carried_gold;
union
Expand Down
2 changes: 1 addition & 1 deletion src/lvl_script_commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -7483,7 +7483,7 @@ const struct CommandDesc command_desc[] = {
{"ADD_TO_PARTY", "ACNNAN ", Cmd_ADD_TO_PARTY, &add_to_party_check, NULL},
{"DELETE_FROM_PARTY", "ACN ", Cmd_DELETE_FROM_PARTY, &delete_from_party_check, NULL},
{"ADD_PARTY_TO_LEVEL", "PAAN ", Cmd_ADD_PARTY_TO_LEVEL, NULL, NULL},
{"ADD_CREATURE_TO_LEVEL", "PCANNN ", Cmd_ADD_CREATURE_TO_LEVEL, NULL, NULL},
{"ADD_CREATURE_TO_LEVEL", "PCANNNa ", Cmd_ADD_CREATURE_TO_LEVEL, NULL, NULL},
{"ADD_OBJECT_TO_LEVEL", "AANpa ", Cmd_ADD_OBJECT_TO_LEVEL, &add_object_to_level_check, &add_object_to_level_process},
{"IF", "PAOAa ", Cmd_IF, &if_check, NULL},
{"IF_ACTION_POINT", "NP ", Cmd_IF_ACTION_POINT, NULL, NULL},
Expand Down
21 changes: 18 additions & 3 deletions src/lvl_script_commands_old.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ static void command_add_party_to_level(long plr_range_id, const char *prtname, c
}
}

static void command_add_creature_to_level(long plr_range_id, const char *crtr_name, const char *locname, long ncopies, long crtr_level, long carried_gold)
static void command_add_creature_to_level(long plr_range_id, const char *crtr_name, const char *locname, long ncopies, long crtr_level, long carried_gold, const char *spawn_type)
{
TbMapLocation location;
if ((crtr_level < 1) || (crtr_level > CREATURE_MAX_LEVEL))
Expand Down Expand Up @@ -147,6 +147,20 @@ static void command_add_creature_to_level(long plr_range_id, const char *crtr_na
SCRPTERRLOG("Unknown creature, '%s'", crtr_name);
return;
}
long spawn_type_id;
if ((strcmp(spawn_type, "") == 0))
{
spawn_type_id = SpwnT_Default;
}
else
{
spawn_type_id = get_rid(spawn_type_desc, spawn_type);
}
if (spawn_type_id == -1)
{
SCRPTERRLOG("Unknown spawn type, '%s'", spawn_type);
return;
}
// Verify player
long plr_id = get_players_range_single(plr_range_id);
if (plr_id < 0) {
Expand All @@ -158,7 +172,7 @@ static void command_add_creature_to_level(long plr_range_id, const char *crtr_na
return;
if (get_script_current_condition() == CONDITION_ALWAYS)
{
script_process_new_creatures(plr_id, crtr_id, location, ncopies, carried_gold, crtr_level-1);
script_process_new_creatures(plr_id, crtr_id, location, ncopies, carried_gold, crtr_level-1, spawn_type_id);
} else
{
struct PartyTrigger* pr_trig = &gameadd.script.party_triggers[gameadd.script.party_triggers_num % PARTY_TRIGGERS_COUNT];
Expand All @@ -171,6 +185,7 @@ static void command_add_creature_to_level(long plr_range_id, const char *crtr_na
pr_trig->carried_gold = carried_gold;
pr_trig->location = location;
pr_trig->ncopies = ncopies;
pr_trig->spawn_type = spawn_type_id;
pr_trig->condit_idx = get_script_current_condition();
gameadd.script.party_triggers_num++;
}
Expand Down Expand Up @@ -1319,7 +1334,7 @@ void script_add_command(const struct CommandDesc *cmd_desc, const struct ScriptL
command_add_party_to_level(scline->np[0], scline->tp[1], scline->tp[2], scline->np[3]);
break;
case Cmd_ADD_CREATURE_TO_LEVEL:
command_add_creature_to_level(scline->np[0], scline->tp[1], scline->tp[2], scline->np[3], scline->np[4], scline->np[5]);
command_add_creature_to_level(scline->np[0], scline->tp[1], scline->tp[2], scline->np[3], scline->np[4], scline->np[5], scline->tp[6]);
break;
case Cmd_ENDIF:
pop_condition();
Expand Down
2 changes: 1 addition & 1 deletion src/lvl_script_value.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ TbResult script_use_spell_on_creature(PlayerNumber plyr_idx, ThingModel crmodel,
* @param destination: The desitination of the disk task.
* @return TbResult whether the spell was successfully cast
*/
TbResult script_computer_dig_to_location(long plyr_idx, long origin, long destination)
TbResult script_computer_dig_to_location(long plyr_idx, TbMapLocation origin, TbMapLocation destination)
{
struct Computer2* comp = get_computer_player(plyr_idx);
long orig_x, orig_y = 0;
Expand Down
10 changes: 5 additions & 5 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1894,7 +1894,7 @@ void level_lost_go_first_person(PlayerNumber plyr_idx)
}

// TODO: replace this function by find_location_pos
void find_map_location_coords(long location, long *x, long *y, int plyr_idx, const char *func_name)
void find_map_location_coords(TbMapLocation location, long *x, long *y, int plyr_idx, const char *func_name)
{
struct ActionPoint *apt;
struct Thing *thing;
Expand Down Expand Up @@ -1978,7 +1978,7 @@ void find_map_location_coords(long location, long *x, long *y, int plyr_idx, con
*x = pos_x;
}

void set_general_information(long msg_id, long target, long x, long y)
void set_general_information(long msg_id, TbMapLocation target, long x, long y)
{
struct PlayerInfo *player;
long pos_x;
Expand All @@ -1995,7 +1995,7 @@ void set_general_information(long msg_id, long target, long x, long y)
event_create_event(pos_x, pos_y, EvKind_Information, player->id_number, -msg_id);
}

void set_quick_information(long msg_id, long target, long x, long y)
void set_quick_information(long msg_id, TbMapLocation target, long x, long y)
{
struct PlayerInfo *player;
long pos_x;
Expand All @@ -2012,12 +2012,12 @@ void set_quick_information(long msg_id, long target, long x, long y)
event_create_event(pos_x, pos_y, EvKind_QuickInformation, player->id_number, -msg_id);
}

void set_general_objective(long msg_id, long target, long x, long y)
void set_general_objective(long msg_id, TbMapLocation target, long x, long y)
{
process_objective(get_string(msg_id), target, x, y);
}

void process_objective(const char *msg_text, long target, long x, long y)
void process_objective(const char *msg_text, TbMapLocation target, long x, long y)
{
struct PlayerInfo *player;
long pos_x;
Expand Down
91 changes: 53 additions & 38 deletions src/thing_creature.c
Original file line number Diff line number Diff line change
Expand Up @@ -6680,12 +6680,16 @@ void illuminate_creature(struct Thing *creatng)
lgt->radius <<= 1;
}

struct Thing *script_create_creature_at_location(PlayerNumber plyr_idx, ThingModel crmodel, TbMapLocation location)
struct Thing *script_create_creature_at_location(PlayerNumber plyr_idx, ThingModel crmodel, TbMapLocation location, char spawn_type)
{
long effect;
long i = get_map_location_longval(location);
struct Coord3d pos;
TbBool fall_from_gate = false;

if (!creature_count_below_map_limit(0))
{
WARNLOG("Could not create creature %s from script to due to creature limit", creature_code_name(crmodel));
return INVALID_THING;
}

switch (get_map_location_type(location))
{
Expand All @@ -6694,29 +6698,39 @@ struct Thing *script_create_creature_at_location(PlayerNumber plyr_idx, ThingMod
{
return INVALID_THING;
}
effect = 1;
if (spawn_type == SpwnT_Default)
{
if (player_is_roaming(plyr_idx))
{
spawn_type = SpwnT_Fall;
}
else
{
spawn_type = SpwnT_None;
}
}
break;
case MLoc_HEROGATE:
if (!get_coords_at_hero_door(&pos, i, 1))
{
return INVALID_THING;
}
effect = 0;
fall_from_gate = true;
if (spawn_type == SpwnT_Default)
{
spawn_type = SpwnT_Jump;
}
break;
case MLoc_PLAYERSHEART:
if (!get_coords_at_dungeon_heart(&pos, i))
{
return INVALID_THING;
}
effect = 0;
break;
case MLoc_METALOCATION:
if (!get_coords_at_meta_action(&pos, plyr_idx, i))
{
return INVALID_THING;
}
effect = 0;
break;
case MLoc_CREATUREKIND:
case MLoc_OBJECTKIND:
Expand All @@ -6728,24 +6742,31 @@ struct Thing *script_create_creature_at_location(PlayerNumber plyr_idx, ThingMod
case MLoc_TRAPKIND:
case MLoc_NONE:
default:
effect = 0;
return INVALID_THING;
}

if (!creature_count_below_map_limit(0))
{
WARNLOG("Could not create creature %s from script to due to creature limit", creature_code_name(crmodel));
return INVALID_THING;
}
struct Thing* thing = create_thing_at_position_then_move_to_valid_and_add_light(&pos, TCls_Creature, crmodel, plyr_idx);
if (thing_is_invalid(thing))
{
ERRORLOG("Couldn't create %s at location %d", creature_code_name(crmodel), (int)location);
// Error is already logged
return INVALID_THING;
}
if (fall_from_gate)

// Lord of the land random speech message.
if (flag_is_set(get_creature_model_flags(thing), CMF_IsLordOfLand))
{
output_message(SMsg_LordOfLandComming, MESSAGE_DELAY_LORD, 1);
output_message(SMsg_EnemyLordQuote + UNSYNC_RANDOM(8), MESSAGE_DELAY_LORD, 1);
}

switch (spawn_type)
{
case SpwnT_Default:
case SpwnT_None:
// no special behavior
break;
case SpwnT_Jump:
set_flag(thing->movement_flags, TMvF_MagicFall);
thing->veloc_push_add.x.val += PLAYER_RANDOM(plyr_idx, 193) - 96;
thing->veloc_push_add.y.val += PLAYER_RANDOM(plyr_idx, 193) - 96;
Expand All @@ -6758,46 +6779,40 @@ struct Thing *script_create_creature_at_location(PlayerNumber plyr_idx, ThingMod
thing->veloc_push_add.z.val += PLAYER_RANDOM(plyr_idx, 96) + 80;
}
set_flag(thing->state_flags, TF1_PushAdd);
}
// Lord of the land random speech message.
if ((get_creature_model_flags(thing) & CMF_IsLordOfLand) != 0)
{
output_message(SMsg_LordOfLandComming, MESSAGE_DELAY_LORD, 1);
output_message(SMsg_EnemyLordQuote + UNSYNC_RANDOM(8), MESSAGE_DELAY_LORD, 1);
}
switch (effect)
{
case 1:
if (player_is_roaming(plyr_idx))
{
thing->mappos.z.val = get_ceiling_height(&thing->mappos);
create_effect(&thing->mappos, TngEff_CeilingBreach, thing->owner);
initialise_thing_state(thing, CrSt_CreatureHeroEntering);
set_flag(thing->rendering_flags, TRF_Invisible);
struct CreatureControl* cctrl = creature_control_get_from_thing(thing);
cctrl->countdown = 24;
}
break;
case SpwnT_Fall:
thing->mappos.z.val = get_ceiling_height(&thing->mappos);
create_effect(&thing->mappos, TngEff_CeilingBreach, thing->owner);
initialise_thing_state(thing, CrSt_CreatureHeroEntering);
set_flag(thing->rendering_flags, TRF_Invisible);
struct CreatureControl* cctrl = creature_control_get_from_thing(thing);
cctrl->countdown = 24;
break;
case SpwnT_Initialize:
init_creature_state(thing);
break;
default:
ERRORLOG("Invalid spawn type %d", spawn_type);
break;
}
return thing;
}

struct Thing *script_create_new_creature(PlayerNumber plyr_idx, ThingModel crmodel, TbMapLocation location, long carried_gold, CrtrExpLevel crtr_level)
struct Thing *script_create_new_creature(PlayerNumber plyr_idx, ThingModel crmodel, TbMapLocation location, long carried_gold, CrtrExpLevel crtr_level, char spawn_type)
{
struct Thing* creatng = script_create_creature_at_location(plyr_idx, crmodel, location);
struct Thing* creatng = script_create_creature_at_location(plyr_idx, crmodel, location, spawn_type);
if (thing_is_invalid(creatng))
return INVALID_THING;
creatng->creature.gold_carried = carried_gold;
init_creature_level(creatng, crtr_level);
return creatng;
}

void script_process_new_creatures(PlayerNumber plyr_idx, ThingModel crmodel, long location, long copies_num, long carried_gold, CrtrExpLevel crtr_level)
void script_process_new_creatures(PlayerNumber plyr_idx, ThingModel crmodel, TbMapLocation location, long copies_num, long carried_gold, CrtrExpLevel crtr_level, char spawn_type)
{
for (long i = 0; i < copies_num; i++)
{
script_create_new_creature(plyr_idx, crmodel, location, carried_gold, crtr_level);
script_create_new_creature(plyr_idx, crmodel, location, carried_gold, crtr_level, spawn_type);
}
}

Expand Down
Loading

0 comments on commit c56493d

Please sign in to comment.