Skip to content

Commit

Permalink
Added Eventful death meta location (dkfans#3739)
Browse files Browse the repository at this point in the history
- Location is called `LAST_DEATH_EVENT[[playername]]` (so `LAST_DEATH_EVENT[PLAYER_GOOD]`)
- It is set whenever a creature dies that has the new EVENTFUL_DEATH creature property
- Resurrecting or fake deaths (creature removed for transfer/growup/...) does not count
  • Loading branch information
Loobinex authored Dec 2, 2024
1 parent 7e751db commit 4a2a543
Show file tree
Hide file tree
Showing 9 changed files with 70 additions and 8 deletions.
1 change: 1 addition & 0 deletions config/creatrs/imp.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ TortureKind = NULL
; ARACHNID - creature is kind of spider.
; DIPTERA - creature is kind of fly.
; LORD - creature is lord of the land, usually arrives to level as final boss, and at arrival you can hear "beware, the lord of the land approaches".
; EVENTFUL_DEATH - when the creature dies the LAST_DEATH_EVENT[] script variable is updated, so mapmaker can use the location.
; SPECTATOR - creature is just a spectator for multiplayer games.
; EVIL - creature has evil nature.
; NEVER_CHICKENS - creature isn't affected by Chicken spell.
Expand Down
1 change: 1 addition & 0 deletions src/config_creature.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ enum CreatureModelFlags {
CMF_Fat = 0x040000, // Creature too fat to walk a full animation.
CMF_NoStealHero = 0x080000, // Prevent the creature from being stolen with the Steal Hero special.
CMF_PreferSteal = 0x100000, // The creature can be generated from Steal Hero special if there's nothing to steal.
CMF_EventfulDeath = 0x200000, // The LAST_DEATH_EVENT[] script location is updated on death.
};

enum CreatureJobFlags {
Expand Down
5 changes: 5 additions & 0 deletions src/config_crtrmodel.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ const struct NamedCommand creatmodel_properties_commands[] = {
{"FAT", 31},
{"NO_STEAL_HERO", 32},
{"PREFER_STEAL", 33},
{"EVENTFUL_DEATH", 34},
{NULL, 0},
};

Expand Down Expand Up @@ -779,6 +780,10 @@ TbBool parse_creaturemodel_attributes_blocks(long crtr_model,char *buf,long len,
crconf->model_flags |= CMF_PreferSteal;
n++;
break;
case 34: // EVENTFUL_DEATH
crconf->model_flags |= CMF_EventfulDeath;
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);
Expand Down
1 change: 1 addition & 0 deletions src/dungeon_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,7 @@ struct Dungeon {
struct TrapInfo mnfct_info;
struct BoxInfo box_info;
struct Coord3d last_combat_location;
struct Coord3d last_eventful_death_location;
int creature_awarded[CREATURE_TYPES_MAX];
unsigned char creature_entrance_level;
unsigned long evil_creatures_converted;
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 @@ -3983,7 +3983,7 @@ static void set_creature_configuration_process(struct ScriptContext* context)
break;
}
default:
CONFWRNLOG("Unrecognized Appearence command (%d)", creature_variable);
CONFWRNLOG("Unrecognized Appearance command (%d)", creature_variable);
break;
}
}
Expand Down
10 changes: 10 additions & 0 deletions src/lvl_script_value.c
Original file line number Diff line number Diff line change
Expand Up @@ -812,6 +812,16 @@ void script_process_value(unsigned long var_index, unsigned long plr_range_id, l
clear_flag(crconf->model_flags,CMF_PreferSteal);
}
break;
case 34: // EVENTFUL_DEATH
if (val4 >= 1)
{
set_flag(crconf->model_flags, CMF_EventfulDeath);
}
else
{
clear_flag(crconf->model_flags, CMF_EventfulDeath);
}
break;
default:
SCRPTERRLOG("Unknown creature property '%ld'", val3);
break;
Expand Down
32 changes: 32 additions & 0 deletions src/map_locations.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ TbBool get_coords_at_meta_action(struct Coord3d *pos, PlayerNumber target_plyr_i
case MML_RECENT_COMBAT:
src = &dungeon->last_combat_location;
break;
case MML_LAST_DEATH_EVENT:
src = &dungeon->last_eventful_death_location;
break;
case MML_ACTIVE_CTA:
if ((dungeon->cta_stl_x == 0) && (dungeon->cta_stl_y == 0))
return false;
Expand Down Expand Up @@ -444,6 +447,35 @@ TbBool get_map_location_id_f(const char *locname, TbMapLocation *location, const
| MLoc_METALOCATION;
return true;
}
else if (strncmp(locname, "LAST_DEATH_EVENT", strlen("LAST_DEATH_EVENT")) == 0)
{
if (strcmp(locname, "LAST_DEATH_EVENT") == 0)
{
if (game.game_kind == GKind_MultiGame)
{
WARNLOG(" %s (line %lu) : LOCATION = '%s' cannot be used on Multiplayer maps", func_name, ln_num, locname);
i = PLAYER0;
}
else
{
i = my_player_number;
}
}
else
{
i = get_player_name_from_location_string(locname);
if (i == -1)
{
ERRORMSG("%s(line %lu): Invalid LOCATION = '%s'", func_name, ln_num, locname);
*location = MLoc_NONE;
return false;
}
}
*location = (((unsigned long)MML_LAST_DEATH_EVENT) << 12)
| ((unsigned long)i << 4)
| MLoc_METALOCATION;
return true;
}
else if (strncmp(locname, "CTA", strlen("CTA")) == 0)
{
if (strcmp(locname, "CTA") == 0)
Expand Down
1 change: 1 addition & 0 deletions src/map_locations.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ enum MetaLocation {
MML_LAST_EVENT = 1,
MML_RECENT_COMBAT,
MML_ACTIVE_CTA,
MML_LAST_DEATH_EVENT,
};

/******************************************************************************/
Expand Down
25 changes: 18 additions & 7 deletions src/thing_creature.c
Original file line number Diff line number Diff line change
Expand Up @@ -2707,27 +2707,38 @@ struct Thing* cause_creature_death(struct Thing *thing, CrDeathFlags flags)
remove_parent_thing_from_things_in_list(&game.thing_lists[TngList_Shots],thing->index);
ThingModel crmodel = thing->model;
struct CreatureStats* crstat = creature_stats_get_from_thing(thing);
if (!thing_exists(thing)) {
flags |= CrDed_NoEffects;
if (!thing_exists(thing))
{
set_flag(flags,CrDed_NoEffects);
}
if (((flags & CrDed_NoEffects) == 0) && (crstat->rebirth != 0)
if ((!flag_is_set(flags,CrDed_NoEffects)) && (crstat->rebirth != 0)
&& (cctrl->lairtng_idx > 0) && (crstat->rebirth-1 <= cctrl->explevel)
&& ((flags & CrDed_NoRebirth) == 0))
&& (!flag_is_set(flags,CrDed_NoRebirth)) )
{
creature_rebirth_at_lair(thing);
return INVALID_THING;
}
creature_throw_out_gold(thing);
// Beyond this point, the creature thing is bound to be deleted
if (((flags & CrDed_NotReallyDying) == 0) || ((game.conf.rules.game.classic_bugs_flags & ClscBug_ResurrectRemoved) != 0))
if ((!flag_is_set(flags,CrDed_NotReallyDying)) || (flag_is_set(game.conf.rules.game.classic_bugs_flags,ClscBug_ResurrectRemoved)))
{
// If the creature is leaving dungeon, or being transformed, then CrDed_NotReallyDying should be set
update_dead_creatures_list_for_owner(thing);
}
if ((flags & CrDed_NoEffects) != 0)
if (flag_is_set(get_creature_model_flags(thing), CMF_EventfulDeath)) //updates LAST_DEATH_EVENT for mapmakers
{
if ((game.flags_cd & MFlg_DeadBackToPool) != 0)
struct Dungeon* dungeon = get_dungeon(thing->owner);
if (!dungeon_invalid(dungeon))
{
memcpy(&dungeon->last_eventful_death_location, &thing->mappos, sizeof(struct Coord3d));
}
}
if (flag_is_set(flags, CrDed_NoEffects))
{
if (flag_is_set(game.flags_cd, MFlg_DeadBackToPool))
{
add_creature_to_pool(crmodel, 1);
}
delete_thing_structure(thing, 0);
} else
if (!creature_model_bleeds(thing->model))
Expand Down

0 comments on commit 4a2a543

Please sign in to comment.