diff --git a/data/mods/Xedra_Evolved/effects/effects.json b/data/mods/Xedra_Evolved/effects/effects.json index 071d43e518df5..81b6f766aea67 100644 --- a/data/mods/Xedra_Evolved/effects/effects.json +++ b/data/mods/Xedra_Evolved/effects/effects.json @@ -1370,6 +1370,14 @@ } ] }, + { + "type": "effect_type", + "id": "effect_homullus_prevented_death", + "name": [ "Transferred Essence" ], + "desc": [ + "You have transferred your essence into a human, saving yourself at the expense of their being. It will take some time until you can do this again." + ] + }, { "type": "effect_type", "id": "telepathic_ignorance", diff --git a/data/mods/Xedra_Evolved/mutations/paraclesians/homullus_eocs.json b/data/mods/Xedra_Evolved/mutations/paraclesians/homullus_eocs.json index c272825926320..f62258946a9c2 100644 --- a/data/mods/Xedra_Evolved/mutations/paraclesians/homullus_eocs.json +++ b/data/mods/Xedra_Evolved/mutations/paraclesians/homullus_eocs.json @@ -361,5 +361,72 @@ "false_effect": [ { "u_message": "You must be within one of the remaining bastions of civilization to cast this spell.", "type": "mixed" } ] + }, + { + "type": "effect_on_condition", + "id": "EOC_HOMULLUS_DEATH_DOOR_REBIRTH", + "eoc_type": "PREVENT_DEATH", + "condition": { + "and": [ { "u_has_trait": "DEATH_IS_BUT_A_DOOR" }, { "not": { "u_has_effect": "effect_homullus_prevented_death" } } ] + }, + "effect": [ + { + "u_location_variable": { "context_val": "homullus_death_door_target" }, + "species": "FERAL", + "target_min_radius": 0, + "target_max_radius": 30 + }, + { + "if": { "math": [ "!has_var(_homullus_death_door_target)" ] }, + "then": [ + { + "u_location_variable": { "context_val": "homullus_death_door_target" }, + "npc": "", + "target_min_radius": 0, + "target_max_radius": 30 + } + ] + }, + { + "if": { "math": [ "has_var(_homullus_death_door_target)" ] }, + "then": [ + { + "run_eocs": { "id": "EOC_HOMULLUS_DEATH_DOOR_KILL_TARGET", "effect": [ { "npc_cast_spell": { "id": "xedra_self_banish" } } ] }, + "beta_loc": { "context_val": "homullus_death_door_target" } + }, + { "math": [ "u_vitamin('blood') = 0" ] }, + "u_prevent_death", + { "math": [ "u_hp('ALL') = 999" ] }, + { "math": [ "u_vitamin('redcells') = 0" ] }, + { "math": [ "u_pain() = 0" ] }, + { "math": [ "u_val('rad') = 0" ] }, + { + "u_lose_effect": [ + "corroding", + "onfire", + "dazed", + "stunned", + "venom_blind", + "formication", + "blisters", + "frostbite", + "frostbite_recovery", + "wet", + "slimed", + "migo_atmosphere", + "fetid_goop", + "sap", + "nausea", + "bleed" + ] + }, + { + "u_add_effect": "effect_homullus_prevented_death", + "duration": { "math": [ "max( 20160, 1209600 - 15120 * u_sum_traits_of_category_char_has('HOMULLUS') )" ] } + }, + { "u_teleport": { "context_val": "homullus_death_door_target" }, "force_safe": true } + ] + } + ] } ] diff --git a/data/mods/Xedra_Evolved/mutations/paraclesians/homullus_mutations.json b/data/mods/Xedra_Evolved/mutations/paraclesians/homullus_mutations.json index b0b79ab4c3aa4..e87d25ba0c732 100644 --- a/data/mods/Xedra_Evolved/mutations/paraclesians/homullus_mutations.json +++ b/data/mods/Xedra_Evolved/mutations/paraclesians/homullus_mutations.json @@ -672,6 +672,18 @@ "threshreq": [ "THRESH_HOMULLUS" ], "enchantments": [ { "values": [ { "value": "MAX_STAMINA", "multiply": 0.33 } ] } ] }, + { + "type": "mutation", + "id": "DEATH_IS_BUT_A_DOOR", + "name": { "str": "Death Is But A Door" }, + "points": 7, + "visibility": 0, + "ugliness": 0, + "description": "One person may die, but their compatriots will carry their torch. You too will have your legacy maintained if you die, but in a way far less metaphorical. When you die, you will reincarnate within any nearby human, immediately shifting their form to match your own. You will not be able to do this more than once per month.", + "category": [ "HOMULLUS" ], + "threshreq": [ "THRESH_HOMULLUS" ], + "//": "An ability that allows the Homullus to be reborn instantly upon death in a nearby feral monster or npc. If one is not nearby the power will fail." + }, { "type": "mutation", "id": "HOMULLUS_DOLL_FORM", diff --git a/data/mods/Xedra_Evolved/spells/classless_spells.json b/data/mods/Xedra_Evolved/spells/classless_spells.json index 435ee66c50585..d102b70d9ef6c 100644 --- a/data/mods/Xedra_Evolved/spells/classless_spells.json +++ b/data/mods/Xedra_Evolved/spells/classless_spells.json @@ -370,5 +370,24 @@ "max_damage": 9999, "base_casting_time": 0, "flags": [ "SILENT", "NO_FAIL" ] + }, + { + "id": "xedra_self_banish", + "type": "SPELL", + "name": { "str": "Banish Self", "//~": "NO_I18N" }, + "description": { + "str": "Banish the caster, killing them and destroying their body. Having this spell is a bug, and casting it would be suicidal.", + "//~": "NO_I18N" + }, + "teachable": false, + "valid_targets": [ "self" ], + "effect": "banishment", + "shape": "blast", + "spell_class": "NONE", + "damage_type": "pure", + "min_damage": 9999, + "max_damage": 9999, + "base_casting_time": 0, + "flags": [ "SILENT", "NO_FAIL", "PERCENT_DAMAGE" ] } ] diff --git a/src/npctalk.cpp b/src/npctalk.cpp index c39476c327ea0..8fab6d348c7ba 100644 --- a/src/npctalk.cpp +++ b/src/npctalk.cpp @@ -4129,6 +4129,10 @@ talk_effect_fun_t::func f_location_variable( const JsonObject &jo, std::string_v target_types++; search_type = "npc"; } + if( jo.has_member( "species" ) ) { + target_types++; + search_type = "species"; + } if( jo.has_member( "trap" ) ) { target_types++; search_type = "trap"; @@ -4140,7 +4144,7 @@ talk_effect_fun_t::func f_location_variable( const JsonObject &jo, std::string_v if( target_types == 1 ) { search_target = get_str_or_var( jo.get_member( search_type.value() ), search_type.value(), true ); } else if( target_types > 1 ) { - jo.throw_error( "Can only have one of terrain, furniture, field, monster, trap, zone, or npc." ); + jo.throw_error( "Can only have one of terrain, furniture, field, monster, species, trap, zone, or npc." ); } var_info var = read_var_info( jo.get_object( member ) ); @@ -4223,6 +4227,17 @@ talk_effect_fun_t::func f_location_variable( const JsonObject &jo, std::string_v g->despawn_nonlocal_monsters(); break; } + } else if( search_type.value() == "species" ) { + Creature *tmp_critter = get_creature_tracker().creature_at( here.get_abs( search_loc ) ); + const species_id species_target( cur_search_target ); + if( tmp_critter != nullptr && tmp_critter->is_monster() && + ( tmp_critter->as_monster()->in_species( species_target ) || + cur_search_target.empty() ) ) { + target_pos = here.get_abs( search_loc ); + found = true; + g->despawn_nonlocal_monsters(); + break; + } } else if( search_type.value() == "npc" ) { for( shared_ptr_fast &person : overmap_buffer.get_npcs_near( project_to( abs_ms ), 1 ) ) {