Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prison & Torture Kind per creature, 2 new fields on the creature config file #3613

Merged
merged 5 commits into from
Nov 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions config/creatrs/imp.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@ Armour = 5
; Every 26 points of difference between shooter dexterity and victim defence gives ~10% to the odds.
; Also, odds can never get higher than 88% or lower than 12%.
Dexterity = 60
; Wounded fear set to 101 will make creature escape from any combat other than
; protecting heart, or a combat with single creature of the same kind.
; Wounded fear set to 101 will make creature escape from any combat other than protecting heart, or a combat with single creature of the same kind.
; This special value works the same way regardless of creature tendencies.
; Smaller value will make the creature escape if it has less than given percentage of health left.
; 0: never escape, 100: escape even if no health is lost.
Expand Down Expand Up @@ -92,6 +91,12 @@ DamageToBoulder = 30
ThingSize = 240 400
; The object the creature will create to use as a lair. Object needs to be configured correctly in objects.cfg too.
LairObject = LAIR_IMP
; Defines the kind of creature it will become if it dies of starvation while imprisoned.
; Setting this to NULL will check if the creature has the 'HUMANOID_SKELETON' property and will default to the room creature creation specified in terrain.cfg.
PrisonKind = NULL
; Defines the kind of creature it will become if it dies from torture.
; The same rule applies as above, except it does not consider the 'HUMANOID_SKELETON' property.
TortureKind = NULL
; Creature properties:
; BLEEDS - the creature leaves blood when is hit, slapped, dying or being injured in any way.
; UNAFFECTED_BY_WIND - the creature isn't pushed back by Wind spell.
Expand Down
36 changes: 36 additions & 0 deletions src/config_crtrmodel.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ const struct NamedCommand creatmodel_attributes_commands[] = {
{"CORPSEVANISHEFFECT", 32},
{"FOOTSTEPPITCH", 33},
{"LAIROBJECT", 34},
{"PRISONKIND", 35},
{"TORTUREKIND", 36},
{NULL, 0},
};

Expand Down Expand Up @@ -281,6 +283,8 @@ TbBool parse_creaturemodel_attributes_blocks(long crtr_model,char *buf,long len,
crstat->flying = false;
crstat->can_see_invisible = false;
crstat->can_go_locked_doors = false;
crstat->prison_kind = 0;
crstat->torture_kind = 0;
crconf->namestr_idx = 0;
crconf->model_flags = 0;
}
Expand Down Expand Up @@ -840,6 +844,38 @@ TbBool parse_creaturemodel_attributes_blocks(long crtr_model,char *buf,long len,
COMMAND_TEXT(cmd_num), block_buf, config_textname);
}
break;
case 35: // PRISONKIND
if (get_conf_parameter_single(buf, &pos, len, word_buf, sizeof(word_buf)) > 0)
{
k = get_id(creature_desc, word_buf);
if (k > 0)
{
crstat->prison_kind = k;
n++;
}
}
if (n < 1)
{
CONFWRNLOG("Incorrect value of \"%s\" parameter in [%s] block of %s file.",
COMMAND_TEXT(cmd_num), block_buf, config_textname);
}
break;
case 36: // TORTUREKIND
if (get_conf_parameter_single(buf, &pos, len, word_buf, sizeof(word_buf)) > 0)
{
k = get_id(creature_desc, word_buf);
if (k > 0)
{
crstat->torture_kind = k;
n++;
}
}
if (n < 1)
{
CONFWRNLOG("Incorrect value of \"%s\" parameter in [%s] block of %s file.",
COMMAND_TEXT(cmd_num), block_buf, config_textname);
}
break;
case ccr_comment:
break;
case ccr_endOfFile:
Expand Down
2 changes: 2 additions & 0 deletions src/creature_control.h
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,8 @@ struct CreatureStats { // These stats are not compatible with original DK - they
unsigned short good_start_state;
unsigned char natural_death_kind;
unsigned char swipe_idx;
ThingModel prison_kind;
ThingModel torture_kind;
struct CreaturePickedUpOffset creature_picked_up_offset;
};

Expand Down
49 changes: 27 additions & 22 deletions src/creature_states_prisn.c
Original file line number Diff line number Diff line change
Expand Up @@ -314,9 +314,15 @@ CrStateRet creature_in_prison(struct Thing *thing)

TbBool prison_convert_creature_to_skeleton(struct Room *room, struct Thing *thing)
{
struct CreatureStats* crstat = creature_stats_get_from_thing(thing);
struct CreatureControl* cctrl = creature_control_get_from_thing(thing);
struct Thing* crthing = INVALID_THING;
long crmodel = get_room_create_creature_model(room->kind); // That normally returns skeleton breed
ThingModel crmodel = crstat->prison_kind;
if ((crmodel > game.conf.crtr_conf.model_count) || (crmodel <= 0))
{
// If not assigned or is unknown, default to the room creature creation.
crmodel = get_room_create_creature_model(room->kind);
}
if (creature_count_below_map_limit(1))
{
crthing = create_creature(&thing->mappos, crmodel, room->owner);
Expand All @@ -334,31 +340,33 @@ TbBool prison_convert_creature_to_skeleton(struct Room *room, struct Thing *thin
}
else
{
WARNLOG("Could not create creature %s to transform %s to due to creature limit", creature_code_name(crmodel),thing_model_name(thing));
WARNLOG("Could not create creature %s to transform %s to due to creature limit", creature_code_name(crmodel), thing_model_name(thing));
}
if (creature_model_bleeds(thing->model)) {
create_effect_around_thing(thing, TngEff_Blood5); // TODO CONFIG: make this effect configurable?
}
if (creature_model_bleeds(thing->model))
create_effect_around_thing(thing, TngEff_Blood5);
kill_creature(thing, INVALID_THING, -1, CrDed_NoEffects);
return !thing_is_invalid(crthing);
}

TbBool process_prisoner_skelification(struct Thing *thing, struct Room *room)
{
struct CreatureStats* crstat = creature_stats_get_from_thing(thing);
if ((thing->health >= 0) || (!crstat->humanoid_creature)) {
if ((thing->health >= 0) || ((!crstat->humanoid_creature) && ((crstat->prison_kind > game.conf.crtr_conf.model_count) || (crstat->prison_kind <= 0)))) {
return false;
}
// TODO CONFIG: (?) Allow 'skelification' only if spent specific amount of turns in prison (set it to low value). (?)
if (CREATURE_RANDOM(thing, 101) > game.conf.rules.rooms.prison_skeleton_chance) {
return false;
}
//TODO CONFIG Allow skeletification only if spent specific amount of turns in prison (set low value)
if (CREATURE_RANDOM(thing, 101) > game.conf.rules.rooms.prison_skeleton_chance)
return false;
if (prison_convert_creature_to_skeleton(room, thing))
{
if (is_my_player_number(room->owner))
{
output_message(SMsg_PrisonMadeSkeleton, 0, true);
}
}
return true; //return true even if no skeleton could be created due to creature limit. Otherwise there's a confusing sound message.
return true; // Return true even if no skeleton could be created due to creature limit. Otherwise there's a confusing sound message.
}

void food_set_wait_to_be_eaten(struct Thing *thing)
Expand Down Expand Up @@ -430,11 +438,7 @@ TbBool process_prison_food(struct Thing *creatng, struct Room *room)
return true;
}

/**
* Does a step of being imprisoned.
* Informs if the imprisoning cycle should end.
* @param thing
*/
/* 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 = get_room_creature_works_in(creatng);
Expand All @@ -450,28 +454,29 @@ CrCheckRet process_prison_function(struct Thing *creatng)
{
return CrCkRet_Deleted;
}
else if ((creatng->health < 0) && (!crstat->humanoid_creature))
{
else if ((creatng->health < 0) && ((!crstat->humanoid_creature) && ((crstat->prison_kind > game.conf.crtr_conf.model_count) || (crstat->prison_kind <= 0))))
{
if (is_my_player_number(room->owner))
{
output_message(SMsg_PrisonersStarving, MESSAGE_DELAY_STARVING, 1);
}
}
struct CreatureControl* cctrl = creature_control_get_from_thing(creatng);
if ((cctrl->instance_id == CrInst_NULL) && process_prison_food(creatng, room) )
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,
// and only if creature sits in jail for long enough
// Breaking from jail is only possible once per some amount of turns, and only if creature sits in jail for long enough.
if (((game.play_gameturn % game.conf.rules.rooms.time_between_prison_break) == 0) &&
(game.play_gameturn > cctrl->imprison.start_gameturn + game.conf.rules.rooms.time_in_prison_without_break))
{
// Check the base jail break condition - whether prison touches enemy land
// Check the base jail break condition - whether prison touches enemy land.
if (jailbreak_possible(room, creatng->owner) && (CREATURE_RANDOM(creatng, 100) < game.conf.rules.rooms.prison_break_chance))
{
if (is_my_player_number(room->owner))
if (is_my_player_number(room->owner)) {
output_message(SMsg_PrisonersEscaping, 40, true);
else if (is_my_player_number(room->owner))
}
else if (is_my_player_number(room->owner)) {
output_message(SMsg_CreatrFreedPrison, 40, true);
}
set_start_state(creatng);
return CrCkRet_Continue;
}
Expand Down
18 changes: 13 additions & 5 deletions src/creature_states_tortr.c
Original file line number Diff line number Diff line change
Expand Up @@ -273,14 +273,20 @@ CrCheckRet process_kinky_function(struct Thing *thing)

void convert_creature_to_ghost(struct Room *room, struct Thing *thing)
{
int crmodel = get_room_create_creature_model(room->kind);
struct CreatureStats* crstat = creature_stats_get_from_thing(thing);
ThingModel crmodel = crstat->torture_kind;
if ((crmodel > game.conf.crtr_conf.model_count) || (crmodel <= 0))
{
// If not assigned or is unknown, default to the room creature creation.
crmodel = get_room_create_creature_model(room->kind);
}
struct Thing* newthing = INVALID_THING;
if (creature_count_below_map_limit(1))
{
newthing = create_creature(&thing->mappos, crmodel, room->owner);
if (thing_is_invalid(newthing))
{
ERRORLOG("Couldn't create creature %s in %s room",creature_code_name(crmodel),room_code_name(room->kind));
ERRORLOG("Couldn't create creature %s in %s room", creature_code_name(crmodel), room_code_name(room->kind));
return;
}
} else
Expand All @@ -290,17 +296,19 @@ void convert_creature_to_ghost(struct Room *room, struct Thing *thing)
struct CreatureControl* cctrl = creature_control_get_from_thing(thing);
struct CreatureControl* newcctrl = creature_control_get_from_thing(newthing);
init_creature_level(newthing, cctrl->explevel);
if (creature_model_bleeds(thing->model))
create_effect_around_thing(newthing, TngEff_Blood5);
if (creature_model_bleeds(thing->model)) {
create_effect_around_thing(newthing, TngEff_Blood5); // TODO CONFIG: make this effect configurable?
}
set_start_state(newthing);
strcpy(newcctrl->creature_name, cctrl->creature_name);
kill_creature(thing, INVALID_THING, -1, CrDed_NoEffects|CrDed_DiedInBattle);
struct Dungeon* dungeon = get_dungeon(room->owner);
if (!dungeon_invalid(dungeon)) {
dungeon->lvstats.ghosts_raised++;
}
if (is_my_player_number(room->owner))
if (is_my_player_number(room->owner)) {
output_message(SMsg_TortureMadeGhost, 0, true);
}
}

void convert_tortured_creature_owner(struct Thing *creatng, PlayerNumber new_owner)
Expand Down
19 changes: 18 additions & 1 deletion src/lvl_script_commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -2818,7 +2818,7 @@ static void set_creature_configuration_check(const struct ScriptLine* scline)
}
else if (creatvar == 34) // LAIROBJECT
{
if (parameter_is_number(scline->tp[2])) //support name or number for lair object
if (parameter_is_number(scline->tp[2])) // Support name or number for lair object.
{
value1 = atoi(scline->tp[2]);
}
Expand All @@ -2827,6 +2827,17 @@ static void set_creature_configuration_check(const struct ScriptLine* scline)
value1 = get_id(object_desc, scline->tp[2]);
}
}
else if ((creatvar == 35) || (creatvar == 36)) // PRISONKIND or TORTUREKIND
{
if (parameter_is_number(scline->tp[2])) // Support name or number for prison kind or torture kind.
{
value1 = atoi(scline->tp[2]);
}
else
{
value1 = get_id(creature_desc, scline->tp[2]);
}
}
else
{
value1 = atoi(scline->tp[2]);
Expand Down Expand Up @@ -3107,6 +3118,12 @@ static void set_creature_configuration_process(struct ScriptContext* context)
crstat->lair_object = value;
}
break;
case 35: // PRISONKIND
crstat->prison_kind = value;
break;
case 36: // TORTUREKIND
crstat->torture_kind = value;
break;
case ccr_comment:
break;
case ccr_endOfFile:
Expand Down