diff --git a/data/mods/MindOverMatter/effectoncondition/eoc_learn_recipes.json b/data/mods/MindOverMatter/effectoncondition/eoc_learn_recipes.json index f76444ef68705..b9b3846e12d68 100644 --- a/data/mods/MindOverMatter/effectoncondition/eoc_learn_recipes.json +++ b/data/mods/MindOverMatter/effectoncondition/eoc_learn_recipes.json @@ -951,6 +951,12 @@ "condition": { "and": [ { "u_has_trait": "TELEPORTER" }, { "math": [ "u_spell_level('teleport_displacement') >= 0" ] } ] }, "effect": [ { "u_learn_recipe": "practice_teleport_displacement" } ] }, + { + "type": "effect_on_condition", + "id": "EOC_CHECK_GAMEBEGIN_TELEPORTER_RECIPE_REACTIVE_DISPLACEMENT", + "condition": { "and": [ { "u_has_trait": "TELEPORTER" }, { "math": [ "u_spell_level('teleport_reactive_displacement') >= 0" ] } ] }, + "effect": [ { "u_learn_recipe": "practice_teleport_reactive_displacement" } ] + }, { "type": "effect_on_condition", "id": "EOC_CHECK_GAMEBEGIN_TELEPORTER_RECIPE_COLLAPSE", @@ -969,6 +975,18 @@ "condition": { "and": [ { "u_has_trait": "TELEPORTER" }, { "math": [ "u_spell_level('teleport_banish') >= 0" ] } ] }, "effect": [ { "u_learn_recipe": "practice_teleport_banish" } ] }, + { + "type": "effect_on_condition", + "id": "EOC_CHECK_GAMEBEGIN_TELEPORTER_RECIPE_LOCI_ESTABLISHMENT", + "condition": { "and": [ { "u_has_trait": "TELEPORTER" }, { "math": [ "u_spell_level('teleport_loci_establishment') >= 0" ] } ] }, + "effect": [ { "u_learn_recipe": "practice_teleport_loci_establishment" } ] + }, + { + "type": "effect_on_condition", + "id": "EOC_CHECK_GAMEBEGIN_TELEPORTER_RECIPE_LOCI_TECHNIQUE", + "condition": { "and": [ { "u_has_trait": "TELEPORTER" }, { "math": [ "u_spell_level('teleport_loci_technique') >= 0" ] } ] }, + "effect": [ { "u_learn_recipe": "practice_teleport_loci_technique" } ] + }, { "type": "effect_on_condition", "id": "EOC_CHECK_GAMEBEGIN_TELEPORTER_RECIPE_GATEWAY", diff --git a/data/mods/MindOverMatter/effectoncondition/eoc_power_effects.json b/data/mods/MindOverMatter/effectoncondition/eoc_power_effects.json index c78bb3b4595e0..0ccdd8cb23019 100644 --- a/data/mods/MindOverMatter/effectoncondition/eoc_power_effects.json +++ b/data/mods/MindOverMatter/effectoncondition/eoc_power_effects.json @@ -325,6 +325,7 @@ "EOC_TELEPATH_REMOVE_SENSE_MINDS", "EOC_TELEPORT_REMOVE_EPHEMERAL_WALK", "EOC_TELEPORT_REMOVE_STRIDE", + "EOC_TELEPORT_REMOVE_REACTIVE_DISPLACEMENT", "EOC_VITAKIN_REMOVE_SLOW_BLEEDING", "EOC_VITAKIN_REMOVE_CONCENTRATED_HEALING", "EOC_VITAKIN_REMOVE_HEALTH_POWER", @@ -409,6 +410,8 @@ "EOC_TELEPATH_REMOVE_SENSE_MINDS", "EOC_TELEPORT_REMOVE_EPHEMERAL_WALK", "EOC_TELEPORT_REMOVE_STRIDE", + "EOC_TELEPORT_REMOVE_REACTIVE_DISPLACEMENT", + "EOC_TELEPORT_REMOVE_LOCI_ESTABLISHMENT", "EOC_VITAKIN_REMOVE_SLOW_BLEEDING", "EOC_VITAKIN_REMOVE_CONCENTRATED_HEALING", "EOC_VITAKIN_REMOVE_HEALTH_POWER", @@ -469,6 +472,8 @@ "Sense Minds", "Ephemeral Walk", "Extended Stride", + "Reactive Displacement", + "Loci Establishment", "Coagulation", "Leukocyte Accumulation", "Healthy Glow", @@ -545,6 +550,7 @@ "EOC_TELEPATH_REMOVE_SENSE_MINDS", "EOC_TELEPORT_REMOVE_EPHEMERAL_WALK", "EOC_TELEPORT_REMOVE_STRIDE", + "EOC_TELEPORT_REMOVE_REACTIVE_DISPLACEMENT", "EOC_VITAKIN_REMOVE_SLOW_BLEEDING", "EOC_VITAKIN_REMOVE_CONCENTRATED_HEALING", "EOC_VITAKIN_REMOVE_HEALTH_POWER", diff --git a/data/mods/MindOverMatter/effects/effects_monster.json b/data/mods/MindOverMatter/effects/effects_monster.json index 393879ec47c89..0bec240db2b27 100644 --- a/data/mods/MindOverMatter/effects/effects_monster.json +++ b/data/mods/MindOverMatter/effects/effects_monster.json @@ -287,6 +287,15 @@ "show_in_info": true, "max_intensity": 20 }, + { + "type": "effect_type", + "id": "effect_teleport_reactive_displacement_monster", + "name": [ "Reactive Displacement" ], + "desc": [ "You will automatically teleport enemies that strike you away from yourself." ], + "show_in_info": true, + "rating": "good", + "enchantments": [ { "hit_me_effect": [ { "id": "teleport_reactive_displacement_monster_teleport" } ] } ] + }, { "type": "effect_type", "id": "effect_riftwalker_teleport", diff --git a/data/mods/MindOverMatter/effects/effects_penalty.json b/data/mods/MindOverMatter/effects/effects_penalty.json index 1c9f3cc70a336..fc6e748597f34 100644 --- a/data/mods/MindOverMatter/effects/effects_penalty.json +++ b/data/mods/MindOverMatter/effects/effects_penalty.json @@ -215,6 +215,8 @@ "effect_telepath_network_effect", "effect_teleport_ephemeral_walk", "effect_teleport_stride", + "effect_teleport_reactive_displacement", + "effect_teleport_loci_establishment", "effect_vita_health", "effect_vitakin_purge_rads", "effect_vitakin_purge_rads_sideeffects", diff --git a/data/mods/MindOverMatter/effects/effects_psionic.json b/data/mods/MindOverMatter/effects/effects_psionic.json index 26423e65bd839..f1d9583475529 100644 --- a/data/mods/MindOverMatter/effects/effects_psionic.json +++ b/data/mods/MindOverMatter/effects/effects_psionic.json @@ -2139,6 +2139,23 @@ } ] }, + { + "type": "effect_type", + "id": "effect_teleport_reactive_displacement", + "name": [ "Reactive Displacement" ], + "desc": [ "You will automatically teleport enemies that strike you away from yourself." ], + "remove_message": "The surrounding matter feels real again.", + "rating": "good", + "enchantments": [ { "hit_me_effect": [ { "id": "teleport_reactive_displacement_teleport" } ] } ] + }, + { + "type": "effect_type", + "id": "effect_teleport_loci_establishment", + "name": [ "Loci Establishment" ], + "desc": [ "You are concentrating on your locus. You can teleport there at will with the [Ψ]Loci Technique." ], + "remove_message": "You've forgotten your locus!.", + "rating": "good" + }, { "type": "effect_type", "id": "effect_teleport_slow", diff --git a/data/mods/MindOverMatter/hobbies.json b/data/mods/MindOverMatter/hobbies.json index 31e719bd6a918..b9e56352f2c4a 100644 --- a/data/mods/MindOverMatter/hobbies.json +++ b/data/mods/MindOverMatter/hobbies.json @@ -422,7 +422,9 @@ { "id": "teleport_displacement", "level": 5 }, { "id": "teleport_stride", "level": 8 }, { "id": "teleport_phase", "level": 11 }, - { "id": "teleport_farstep", "level": 5 } + { "id": "teleport_farstep", "level": 5 }, + { "id": "teleport_loci_establishment", "level": 2 }, + { "id": "teleport_loci_technique", "level": 2 } ] }, { @@ -438,12 +440,15 @@ { "id": "teleport_blink", "level": 11 }, { "id": "teleport_slow", "level": 12 }, { "id": "teleport_displacement", "level": 10 }, + { "id": "teleport_reactive_displacement", "level": 5 }, { "id": "teleport_stride", "level": 12 }, { "id": "teleport_phase", "level": 12 }, { "id": "teleport_ephemeral_walk", "level": 4 }, { "id": "teleport_collapse", "level": 7 }, { "id": "teleport_farstep", "level": 10 }, { "id": "teleport_banish", "level": 6 }, + { "id": "teleport_loci_establishment", "level": 5 }, + { "id": "teleport_loci_technique", "level": 5 }, { "id": "teleport_gateway", "level": 4 } ] }, diff --git a/data/mods/MindOverMatter/monsters/feral_psychics.json b/data/mods/MindOverMatter/monsters/feral_psychics.json index 33d72fca7e816..ef107eead49b8 100644 --- a/data/mods/MindOverMatter/monsters/feral_psychics.json +++ b/data/mods/MindOverMatter/monsters/feral_psychics.json @@ -1249,6 +1249,19 @@ "miss_msg_u": "%s reaches for you but you avoid their touch!", "miss_msg_npc": "%s reaches for but they dodge!" }, + { + "id": "psi_porter2_reactive_displacement", + "type": "spell", + "spell_data": { "id": "teleporter_reactive_displacement_monster" }, + "cooldown": 1, + "condition": { + "and": [ + { "not": { "u_has_flag": "NO_PSIONICS" } }, + { "not": { "u_has_effect": "effect_teleport_reactive_displacement_monster" } } + ] + }, + "monster_message": "The space around %1$s distorts." + }, { "type": "leap", "cooldown": { "math": [ "1 + rand(2)" ] }, @@ -1314,6 +1327,19 @@ "condition": { "not": { "u_has_flag": "NO_PSIONICS" } }, "monster_message": "%1$s touches %3$s and the world around %3$s wavers." }, + { + "id": "psi_porter3_reactive_displacement", + "type": "spell", + "spell_data": { "id": "teleporter_reactive_displacement_monster" }, + "cooldown": 1, + "condition": { + "and": [ + { "not": { "u_has_flag": "NO_PSIONICS" } }, + { "not": { "u_has_effect": "effect_teleport_reactive_displacement_monster" } } + ] + }, + "monster_message": "The space around %1$s distorts." + }, { "type": "leap", "cooldown": 1, diff --git a/data/mods/MindOverMatter/monsters/monsters_spells.json b/data/mods/MindOverMatter/monsters/monsters_spells.json index d042ca8608097..b41907f93c9e1 100644 --- a/data/mods/MindOverMatter/monsters/monsters_spells.json +++ b/data/mods/MindOverMatter/monsters/monsters_spells.json @@ -1158,6 +1158,55 @@ "casting_time_increment": -4, "ignored_monster_species": [ "PSI_NULL" ] }, + { + "type": "SPELL", + "id": "teleporter_reactive_displacement_monster", + "name": { "str": "Reactive Displacement Monster enemy check", "//~": "NO_I18N" }, + "description": { "str": "Preps for using Reactive Displaccement when a hostile target is detected.", "//~": "NO_I18N" }, + "flags": [ "SILENT", "NO_HANDS", "NO_LEGS", "MUST_HAVE_CLASS_TO_LEARN" ], + "valid_targets": [ "hostile" ], + "max_level": 1, + "effect": "attack", + "extra_effects": [ { "id": "teleporter_reactive_displacement_monster_self", "hit_self": true } ], + "shape": "blast", + "min_range": 60, + "max_range": 60 + }, + { + "type": "SPELL", + "id": "teleporter_reactive_displacement_monster_self", + "name": { "str": "Reactive Displacement Monster give Effect", "//~": "NO_I18N" }, + "description": { "str": "Grants the Reactive Displacement effect to a monster.", "//~": "NO_I18N" }, + "flags": [ "NO_HANDS", "NO_LEGS", "MUST_HAVE_CLASS_TO_LEARN", "RANDOM_DURATION" ], + "valid_targets": [ "self" ], + "max_level": 1, + "effect": "attack", + "effect_str": "effect_teleport_reactive_displacement_monster", + "shape": "blast", + "min_duration": 12000, + "max_duration": 42000 + }, + { + "id": "teleport_reactive_displacement_monster_teleport", + "type": "SPELL", + "name": { "str": "Reactive Displacement Monster Teleport", "//~": "NO_I18N" }, + "description": { "str": "Teleports Attackers.", "//~": "NO_I18N" }, + "teachable": false, + "valid_targets": [ "ally", "hostile" ], + "spell_class": "TELEPORTER", + "skill": "metaphysics", + "flags": [ "PSIONIC", "CONCENTRATE", "SILENT", "NO_HANDS", "NO_LEGS", "NO_EXPLOSION_SFX" ], + "difficulty": 0, + "max_level": 0, + "effect": "attack", + "shape": "blast", + "damage_type": "psi_teleporter_teleporting_damage", + "min_damage": 1, + "max_damage": 1, + "min_range": 1, + "energy_source": "NONE", + "ignored_monster_species": [ "PSI_NULL" ] + }, { "id": "teleporter_breach_monster", "type": "SPELL", diff --git a/data/mods/MindOverMatter/monsters/triffids.json b/data/mods/MindOverMatter/monsters/triffids.json index 67e2646f517fb..7ebe07700bf36 100644 --- a/data/mods/MindOverMatter/monsters/triffids.json +++ b/data/mods/MindOverMatter/monsters/triffids.json @@ -103,6 +103,19 @@ "condition": { "not": { "u_has_flag": "NO_PSIONICS" } }, "message": "%1$s vanishes and reappears elsewhere!" }, + { + "id": "psi_porter3_reactive_displacement", + "type": "spell", + "spell_data": { "id": "teleporter_reactive_displacement_monster" }, + "cooldown": 1, + "condition": { + "and": [ + { "not": { "u_has_flag": "NO_PSIONICS" } }, + { "not": { "u_has_effect": "effect_teleport_reactive_displacement_monster" } } + ] + }, + "monster_message": "The space around %1$s distorts." + }, { "id": "psi_triffid_teleporter_ally_teleport", "type": "spell", diff --git a/data/mods/MindOverMatter/powers/learning_eocs/teleportation.json b/data/mods/MindOverMatter/powers/learning_eocs/teleportation.json index cf345462ad670..cafe66d45dafe 100644 --- a/data/mods/MindOverMatter/powers/learning_eocs/teleportation.json +++ b/data/mods/MindOverMatter/powers/learning_eocs/teleportation.json @@ -172,6 +172,40 @@ } ] }, + { + "type": "effect_on_condition", + "id": "EOC_TELEPORT_LEARNING_REACTIVE_DISPLACEMENT", + "recurrence": [ + { "math": [ "jmath_teleportation_learning_eocs_modifiers(global_tier_two_power_learning_time_low)" ] }, + { "math": [ "jmath_teleportation_learning_eocs_modifiers(global_tier_two_power_learning_time_high)" ] } + ], + "condition": { + "and": [ + { "u_has_trait": "TELEPORTER" }, + { "math": [ "u_vitamin('vitamin_psi_learning_counter') == 1" ] }, + { + "or": [ + { "test_eoc": "EOC_CONDITION_ODDS_OF_RANDOM_TIER_TWO_POWER_INSIGHT" }, + { "and": [ { "math": [ "u_spell_level('teleport_displacement') >= 5" ] } ] } + ] + }, + { "test_eoc": "EOC_PSI_LEARNING_BANNED_EFFECTS" }, + { "math": [ "u_spell_level('teleport_reactive_displacement') <= 0" ] }, + { "not": { "u_know_recipe": "practice_teleport_reactive_displacement" } } + ] + }, + "deactivate_condition": { + "or": [ { "not": { "u_has_trait": "TELEPORTER" } }, { "math": [ "u_spell_level('teleport_reactive_displacement') >= 1" ] } ] + }, + "effect": [ + { "math": [ "u_vitamin('vitamin_psi_learning_counter') = 0" ] }, + { "u_learn_recipe": "practice_teleport_reactive_displacement" }, + { + "u_message": "Use of your powers has led to an insight. You could automatically teleport away attacking enemies, if you can figure out the technique.", + "popup": true + } + ] + }, { "type": "effect_on_condition", "id": "EOC_TELEPORT_LEARNING_COLLAPSE", @@ -293,6 +327,42 @@ } ] }, + { + "type": "effect_on_condition", + "id": "EOC_TELEPORT_LEARNING_LOCI_ESTABLISHMENT", + "recurrence": [ + { "math": [ "jmath_teleportation_learning_eocs_modifiers(global_tier_two_power_learning_time_low)" ] }, + { "math": [ "jmath_teleportation_learning_eocs_modifiers(global_tier_two_power_learning_time_high)" ] } + ], + "condition": { + "and": [ + { "u_has_trait": "TELEPORTER" }, + { "math": [ "u_vitamin('vitamin_psi_learning_counter') == 1" ] }, + { + "or": [ + { "test_eoc": "EOC_CONDITION_ODDS_OF_RANDOM_TIER_TWO_POWER_INSIGHT" }, + { + "and": [ { "math": [ "u_spell_level('teleport_stride') >= 6" ] }, { "math": [ "u_spell_level('teleport_farstep') >= 6" ] } ] + } + ] + }, + { "test_eoc": "EOC_PSI_LEARNING_BANNED_EFFECTS" }, + { "math": [ "u_spell_level('teleport_loci_establishment') <= 0" ] }, + { "not": { "u_know_recipe": "practice_teleport_loci_establishment" } } + ] + }, + "deactivate_condition": { + "or": [ { "not": { "u_has_trait": "TELEPORTER" } }, { "math": [ "u_spell_level('teleport_loci_establishment') >= 1" ] } ] + }, + "effect": [ + { "math": [ "u_vitamin('vitamin_psi_learning_counter') = 0" ] }, + { "u_learn_recipe": "practice_teleport_loci_establishment" }, + { + "u_message": "Use of your powers has led to an insight. You could concentrate on a specific location and teleport there at will.", + "popup": true + } + ] + }, { "type": "effect_on_condition", "id": "EOC_TELEPORT_LEARNING_GATEWAY", @@ -308,7 +378,10 @@ "or": [ { "test_eoc": "EOC_CONDITION_ODDS_OF_RANDOM_TIER_THREE_POWER_INSIGHT" }, { - "and": [ { "math": [ "u_spell_level('teleport_stride') >= 10" ] }, { "math": [ "u_spell_level('teleport_farstep') >= 10" ] } ] + "and": [ + { "math": [ "u_spell_level('teleport_loci_establishment') >= 6" ] }, + { "math": [ "u_spell_level('teleport_farstep') >= 10" ] } + ] } ] }, @@ -327,6 +400,42 @@ } ] }, + { + "type": "effect_on_condition", + "id": "EOC_TELEPORT_LEARNING_dilated_gateway", + "recurrence": [ + { "math": [ "jmath_teleportation_learning_eocs_modifiers(global_tier_three_power_learning_time_low)" ] }, + { "math": [ "jmath_teleportation_learning_eocs_modifiers(global_tier_three_power_learning_time_high)" ] } + ], + "condition": { + "and": [ + { "u_has_trait": "TELEPORTER" }, + { "math": [ "u_vitamin('vitamin_psi_learning_counter') == 1" ] }, + { + "or": [ + { "test_eoc": "EOC_CONDITION_ODDS_OF_RANDOM_TIER_THREE_POWER_INSIGHT" }, + { + "and": [ { "math": [ "u_spell_level('teleport_gateway') >= 8" ] }, { "math": [ "u_spell_level('teleport_banish') >= 2" ] } ] + } + ] + }, + { "test_eoc": "EOC_PSI_LEARNING_BANNED_EFFECTS" }, + { "math": [ "u_spell_level('teleport_dilated_gateway') <= 0" ] }, + { "not": { "u_know_recipe": "practice_teleport_dilated_gateway" } } + ] + }, + "deactivate_condition": { + "or": [ { "not": { "u_has_trait": "TELEPORTER" } }, { "math": [ "u_spell_level('teleport_dilated_gateway') >= 1" ] } ] + }, + "effect": [ + { "math": [ "u_vitamin('vitamin_psi_learning_counter') = 0" ] }, + { "u_learn_recipe": "practice_teleport_dilated_gateway" }, + { + "u_message": "Use of your powers has led to an insight. Just as you can teleport yourself to memorized locations, you can also teleport other beings to those same locations alongside you.", + "popup": true + } + ] + }, { "type": "effect_on_condition", "id": "EOC_TELEPORT_LEARNING_BREACH", diff --git a/data/mods/MindOverMatter/powers/teleportation.json b/data/mods/MindOverMatter/powers/teleportation.json index 9c1fc900db22e..d00cf567474ff 100644 --- a/data/mods/MindOverMatter/powers/teleportation.json +++ b/data/mods/MindOverMatter/powers/teleportation.json @@ -232,6 +232,64 @@ "casting_time_increment": -4, "ignored_monster_species": [ "PSI_NULL" ] }, + { + "id": "teleport_reactive_displacement", + "type": "SPELL", + "name": "[Ψ]Reactive Displacement (C)", + "description": "Maintain a field of unstable space around you, allowing you to effortlessly teleport enemies that strike you further away. Unfortunately, their attacks will still hurt you as normal.\n\nThis power is maintained by concentration and may fail if concentration is interrupted.", + "teachable": false, + "valid_targets": [ "self" ], + "spell_class": "TELEPORTER", + "skill": "metaphysics", + "flags": [ "PSIONIC", "CONCENTRATE", "SILENT", "NO_HANDS", "NO_LEGS", "RANDOM_DURATION", "NO_EXPLOSION_SFX" ], + "difficulty": 5, + "max_level": { "math": [ "int_to_level(1)" ] }, + "effect": "effect_on_condition", + "effect_str": "EOC_TELEPORT_REACTIVE_DISPLACEMENT_INITIATE", + "shape": "blast", + "min_duration": { + "math": [ + "( ( u_spell_level('teleport_reactive_displacement') * 1000 ) + 2000 ) * ( scaling_factor( u_val('intelligence') ) ) * u_nether_attunement_power_scaling" + ] + }, + "max_duration": { + "math": [ + "( ( u_spell_level('teleport_reactive_displacement') * 4000 ) + 20000 ) * ( scaling_factor( u_val('intelligence') ) ) * u_nether_attunement_power_scaling" + ] + }, + "energy_source": "STAMINA", + "base_energy_cost": { + "math": [ + "u_effect_intensity('effect_teleport_reactive_displacement') > -1 ? 0 : max( ( 3500 - ( u_spell_level('teleport_reactive_displacement') * 100 ) ), 1500 )" + ] + }, + "base_casting_time": { + "math": [ + "u_effect_intensity('effect_teleport_reactive_displacement') > -1 ? 10 : max( ( 100 - ( u_spell_level('teleport_reactive_displacement') * 5 ) ), 25 )" + ] + } + }, + { + "id": "teleport_reactive_displacement_teleport", + "type": "SPELL", + "name": "[Ψ]Reactive Displacement (C) - Teleport", + "description": "The actual teleport effect of reactive displacement. Having this spell is a bug.", + "teachable": false, + "valid_targets": [ "ally", "hostile" ], + "spell_class": "TELEPORTER", + "skill": "metaphysics", + "flags": [ "PSIONIC", "CONCENTRATE", "SILENT", "NO_HANDS", "NO_LEGS", "NO_EXPLOSION_SFX" ], + "difficulty": 0, + "max_level": 0, + "effect": "attack", + "shape": "blast", + "damage_type": "psi_teleporter_teleporting_damage", + "min_damage": 1, + "max_damage": 1, + "min_range": 1, + "energy_source": "NONE", + "ignored_monster_species": [ "PSI_NULL" ] + }, { "id": "teleport_collapse", "type": "SPELL", @@ -626,6 +684,67 @@ "max_range": 0, "ignored_monster_species": [ "PSI_NULL" ] }, + { + "id": "teleport_loci_establishment", + "type": "SPELL", + "name": "[Ψ]Loci Establishment (C)", + "description": "Start concentrating on your current location, allowing you to return here at will with the [Ψ]Loci Technique power.\n\nThis power is maintained by concentration and may fail if concentration is interrupted.", + "teachable": false, + "valid_targets": [ "self" ], + "spell_class": "TELEPORTER", + "skill": "metaphysics", + "flags": [ "PSIONIC", "CONCENTRATE", "SILENT", "NO_HANDS", "NO_LEGS", "RANDOM_DURATION", "NO_EXPLOSION_SFX" ], + "difficulty": 6, + "max_level": { "math": [ "int_to_level(1)" ] }, + "effect": "effect_on_condition", + "effect_str": "EOC_TELEPORT_LOCI_ESTABLISHMENT_INITIATE", + "shape": "blast", + "min_duration": { + "math": [ + "( ( u_spell_level('teleport_loci_establishment') * 2500 ) + 12500 ) * ( scaling_factor( u_val('intelligence') ) ) * u_nether_attunement_power_scaling" + ] + }, + "max_duration": { + "math": [ + "( ( u_spell_level('teleport_loci_establishment') * 5000 ) + 25000 ) * ( scaling_factor( u_val('intelligence') ) ) * u_nether_attunement_power_scaling" + ] + }, + "energy_source": "STAMINA", + "base_energy_cost": { + "math": [ + "u_effect_intensity('effect_teleport_loci_establishment') > -1 ? 0 : max( ( 3000 - ( u_spell_level('teleport_reactive_displacement') * 100 ) ), 1000 )" + ] + }, + "base_casting_time": { + "math": [ + "u_effect_intensity('effect_teleport_loci_establishment') > -1 ? 10 : max( ( 100 - ( u_spell_level('teleport_reactive_displacement') * 5 ) ), 25 )" + ] + } + }, + { + "id": "teleport_loci_technique", + "type": "SPELL", + "name": "[Ψ]Loci Technique", + "description": "Transport yourself through the nether to your established loci location. You must currently be concentrating on your [Ψ]Loci Establishment (C) for this to function.", + "message": "", + "teachable": false, + "valid_targets": [ "self" ], + "spell_class": "TELEPORTER", + "skill": "metaphysics", + "flags": [ "PSIONIC", "CONCENTRATE", "SILENT", "NO_HANDS", "NO_LEGS" ], + "difficulty": 6, + "max_level": { "math": [ "int_to_level(1)" ] }, + "effect": "effect_on_condition", + "effect_str": "EOC_TELEPORT_LOCI_TECHNIQUE", + "shape": "blast", + "energy_source": "STAMINA", + "base_energy_cost": 6000, + "final_energy_cost": 3000, + "energy_increment": -200, + "base_casting_time": 200, + "final_casting_time": 75, + "casting_time_increment": -5.5 + }, { "id": "teleport_gateway", "type": "SPELL", @@ -650,6 +769,67 @@ "final_casting_time": 75, "casting_time_increment": -5.5 }, + { + "id": "teleport_dilated_gateway", + "type": "SPELL", + "name": "[Ψ]Dilated Gateway", + "description": "Transport yourself and every adjacent creature to a chosen location. You must have already attuned an area with [Ψ]Gateway.", + "message": "", + "teachable": false, + "valid_targets": [ "self" ], + "spell_class": "TELEPORTER", + "skill": "metaphysics", + "flags": [ "PSIONIC", "CONCENTRATE", "SILENT", "NO_HANDS", "NO_LEGS" ], + "difficulty": 9, + "max_level": { "math": [ "int_to_level(1)" ] }, + "effect": "effect_on_condition", + "effect_str": "EOC_TELEPORT_dilated_gateway_SELECTOR", + "shape": "blast", + "energy_source": "STAMINA", + "base_energy_cost": 12000, + "final_energy_cost": 8000, + "energy_increment": -200, + "base_casting_time": 200, + "final_casting_time": 75, + "casting_time_increment": -5.5 + }, + { + "id": "teleport_dilated_gateway_teleport_others", + "type": "SPELL", + "name": "[Ψ]Dilated Gateway - Teleport Others", + "description": "The spell that actually teleports the adjacent targets. Should only be casted via teleport_gateway_other's EOC.", + "message": "", + "teachable": false, + "valid_targets": [ "ally", "hostile" ], + "spell_class": "TELEPORTER", + "skill": "metaphysics", + "flags": [ "PSIONIC", "CONCENTRATE", "SILENT", "NO_HANDS", "NO_LEGS", "NO_FAIL", "NO_PROJECTILE" ], + "difficulty": 0, + "max_level": 0, + "min_aoe": 1, + "effect": "effect_on_condition", + "effect_str": "EOC_TELEPORT_EXTERNAL_TELEPORT", + "shape": "blast", + "energy_source": "NONE" + }, + { + "id": "teleport_dilated_gateway_teleport_self", + "type": "SPELL", + "name": "[Ψ]Dilated Gateway - Teleport Self", + "description": "The spell that actually teleports the player. Should only be casted via teleport_gateway_other's EOC.", + "message": "", + "teachable": false, + "valid_targets": [ "self" ], + "spell_class": "TELEPORTER", + "skill": "metaphysics", + "flags": [ "PSIONIC", "CONCENTRATE", "SILENT", "NO_HANDS", "NO_LEGS", "NO_FAIL", "NO_PROJECTILE" ], + "difficulty": 0, + "max_level": 0, + "effect": "effect_on_condition", + "effect_str": "EOC_TELEPORT_EXTERNAL_TELEPORT", + "shape": "blast", + "energy_source": "NONE" + }, { "id": "teleport_summon", "type": "SPELL", diff --git a/data/mods/MindOverMatter/powers/teleportation_concentration_eoc.json b/data/mods/MindOverMatter/powers/teleportation_concentration_eoc.json index 7fd88342809a8..791c08180c506 100644 --- a/data/mods/MindOverMatter/powers/teleportation_concentration_eoc.json +++ b/data/mods/MindOverMatter/powers/teleportation_concentration_eoc.json @@ -116,5 +116,124 @@ } ], "false_effect": [ ] + }, + { + "type": "effect_on_condition", + "id": "EOC_TELEPORT_REACTIVE_DISPLACEMENT_INITIATE", + "condition": { "not": { "u_has_effect": "effect_teleport_reactive_displacement" } }, + "effect": [ + { "u_message": "You are prepared to displace your attackers.", "type": "good" }, + { "run_eocs": "EOC_POWER_MAINTENANCE_PLUS_ONE" }, + { "u_add_effect": "effect_teleport_reactive_displacement", "duration": "PERMANENT" }, + { + "run_eocs": "EOC_TELEPORT_REACTIVE_DISPLACEMENT_DRAIN", + "time_in_future": [ + { + "math": [ + "( ( u_spell_level('teleport_reactive_displacement') * 1 ) + 20 ) * ( scaling_factor( u_val('intelligence') ) ) * u_nether_attunement_power_scaling" + ] + }, + { + "math": [ + "( ( u_spell_level('teleport_reactive_displacement') * 4 ) + 200 ) * ( scaling_factor( u_val('intelligence') ) ) * u_nether_attunement_power_scaling" + ] + } + ] + } + ], + "false_effect": [ { "run_eocs": "EOC_TELEPORT_REMOVE_REACTIVE_DISPLACEMENT" } ] + }, + { + "type": "effect_on_condition", + "id": "EOC_TELEPORT_REMOVE_REACTIVE_DISPLACEMENT", + "condition": { "u_has_effect": "effect_teleport_reactive_displacement" }, + "effect": [ { "run_eocs": "EOC_POWER_MAINTENANCE_MINUS_ONE" }, { "u_lose_effect": "effect_teleport_reactive_displacement" } ] + }, + { + "type": "effect_on_condition", + "id": "EOC_TELEPORT_REACTIVE_DISPLACEMENT_DRAIN", + "condition": { "u_has_effect": "effect_teleport_reactive_displacement" }, + "effect": [ + { "math": [ "u_latest_channeled_power_difficulty = 5" ] }, + { "run_eocs": [ "EOC_PSIONICS_GAIN_NETHER_ATTUNEMENT_2", "EOC_PSI_MAINTENANCE_CALORIE_COST_CALCULATOR" ] }, + { "math": [ "u_spell_exp('teleport_reactive_displacement') += (maintenance_exp_factor(u_val('focus')))" ] }, + { "run_eocs": "EOC_POWER_MAINTENANCE_CONCENTRATION_CHECK" }, + { + "run_eocs": "EOC_TELEPORT_REACTIVE_DISPLACEMENT_DRAIN", + "time_in_future": [ + { + "math": [ + "( ( u_spell_level('teleport_reactive_displacement') * 2 ) + 20 ) * ( scaling_factor( u_val('intelligence') ) ) * u_nether_attunement_power_scaling" + ] + }, + { + "math": [ + "( ( u_spell_level('teleport_reactive_displacement') * 4 ) + 200 ) * ( scaling_factor( u_val('intelligence') ) ) * u_nether_attunement_power_scaling" + ] + } + ] + } + ], + "false_effect": [ ] + }, + { + "type": "effect_on_condition", + "id": "EOC_TELEPORT_LOCI_ESTABLISHMENT_INITIATE", + "condition": { "not": { "u_has_effect": "effect_teleport_loci_establishment" } }, + "effect": [ + { "u_message": "You are prepared to displace your attackers.", "type": "good" }, + { "run_eocs": "EOC_POWER_MAINTENANCE_PLUS_ONE" }, + { "u_location_variable": { "u_val": "teleporter_loci_establishment_loc" }, "min_radius": 0, "max_radius": 0 }, + { "u_add_effect": "effect_teleport_loci_establishment", "duration": "PERMANENT" }, + { + "run_eocs": "EOC_TELEPORT_LOCI_ESTABLISHMENT_DRAIN", + "time_in_future": [ + { + "math": [ + "( ( u_spell_level('teleport_loci_establishment') * 1 ) + 20 ) * ( scaling_factor( u_val('intelligence') ) ) * u_nether_attunement_power_scaling" + ] + }, + { + "math": [ + "( ( u_spell_level('teleport_loci_establishment') * 4 ) + 200 ) * ( scaling_factor( u_val('intelligence') ) ) * u_nether_attunement_power_scaling" + ] + } + ] + } + ], + "false_effect": [ { "run_eocs": "EOC_TELEPORT_REMOVE_LOCI_ESTABLISHMENT" } ] + }, + { + "type": "effect_on_condition", + "id": "EOC_TELEPORT_REMOVE_LOCI_ESTABLISHMENT", + "condition": { "u_has_effect": "effect_teleport_loci_establishment" }, + "effect": [ { "run_eocs": "EOC_POWER_MAINTENANCE_MINUS_ONE" }, { "u_lose_effect": "effect_teleport_loci_establishment" } ] + }, + { + "type": "effect_on_condition", + "id": "EOC_TELEPORT_LOCI_ESTABLISHMENT_DRAIN", + "condition": { "u_has_effect": "effect_teleport_loci_establishment" }, + "effect": [ + { "math": [ "u_latest_channeled_power_difficulty = 6" ] }, + { "run_eocs": [ "EOC_PSIONICS_GAIN_NETHER_ATTUNEMENT_2", "EOC_PSI_MAINTENANCE_CALORIE_COST_CALCULATOR" ] }, + { "math": [ "u_spell_exp('teleport_loci_establishment') +=(maintenance_exp_factor(u_val('focus')))" ] }, + { "run_eocs": "EOC_POWER_MAINTENANCE_CONCENTRATION_CHECK" }, + { + "run_eocs": "EOC_TELEPORT_LOCI_ESTABLISHMENT_DRAIN", + "time_in_future": [ + { + "math": [ + "( ( u_spell_level('teleport_loci_establishment') * 2 ) + 20 ) * ( scaling_factor( u_val('intelligence') ) ) * u_nether_attunement_power_scaling" + ] + }, + { + "math": [ + "( ( u_spell_level('teleport_loci_establishment') * 4 ) + 200 ) * ( scaling_factor( u_val('intelligence') ) ) * u_nether_attunement_power_scaling" + ] + } + ] + } + ], + "false_effect": [ ] } ] diff --git a/data/mods/MindOverMatter/powers/teleportation_eoc.json b/data/mods/MindOverMatter/powers/teleportation_eoc.json index f6bec517360ee..69865992849b5 100644 --- a/data/mods/MindOverMatter/powers/teleportation_eoc.json +++ b/data/mods/MindOverMatter/powers/teleportation_eoc.json @@ -771,6 +771,134 @@ { "run_eocs": "EOC_TELEPORTER_ATTUNED_MESSAGE" } ] }, + { + "type": "effect_on_condition", + "id": "EOC_TELEPORT_dilated_gateway_SELECTOR", + "effect": [ + { + "run_eoc_selector": [ + "EOC_TELEPORT_dilated_gateway_SELECT_01", + "EOC_TELEPORT_dilated_gateway_SELECT_02", + "EOC_TELEPORT_dilated_gateway_SELECT_03", + "EOC_TELEPORT_dilated_gateway_SELECT_04", + "EOC_TELEPORT_dilated_gateway_SELECT_05", + "EOC_TELEPORT_dilated_gateway_SELECT_06", + "EOC_TELEPORT_dilated_gateway_SELECT_07", + "EOC_TELEPORT_dilated_gateway_SELECT_08", + "EOC_TELEPORT_dilated_gateway_SELECT_09", + "EOC_TELEPORT_dilated_gateway_SELECT_10" + ], + "names": [ + "Dilated Gateway: ", + "Dilated Gateway: ", + "Dilated Gateway: ", + "Dilated Gateway: ", + "Dilated Gateway: ", + "Dilated Gateway: ", + "Dilated Gateway: ", + "Dilated Gateway: ", + "Dilated Gateway: ", + "Dilated Gateway: " + ], + "keys": [ "1", "2", "3", "4", "5", "6", "7", "8", "9", "0" ], + "descriptions": [ + "Teleport target to a destination.", + "Teleport target to a destination.", + "Teleport target to a destination.", + "Teleport target to a destination.", + "Teleport target to a destination.", + "Teleport target to a destination.", + "Teleport target to a destination.", + "Teleport target to a destination.", + "Teleport target to a destination.", + "Teleport target to a destination." + ], + "hide_failing": true, + "allow_cancel": true + }, + { + "if": { "not": { "compare_string": [ { "u_val": "dilated_gateway_location" }, "" ] } }, + "then": [ + { "u_cast_spell": { "id": "teleport_dilated_gateway_teleport_others", "message": "" } }, + { "u_cast_spell": { "id": "teleport_dilated_gateway_teleport_self", "message": "" } } + ] + }, + { "set_string_var": "", "target_var": { "u_val": "dilated_gateway_location" } } + ] + }, + { + "type": "effect_on_condition", + "id": "EOC_TELEPORT_EXTERNAL_TELEPORT", + "effect": [ + { + "set_string_var": "", + "target_var": { "context_val": "temp_var" }, + "parse_tags": true + }, + { "u_teleport": { "var_val": "temp_var" }, "force_safe": true }, + { "message": " vanishes!" } + ] + }, + { + "type": "effect_on_condition", + "id": "EOC_TELEPORT_dilated_gateway_SELECT_01", + "condition": { "math": [ "has_var(u_gateway_destination_1)" ] }, + "effect": [ { "set_string_var": "npc_gateway_destination_1", "target_var": { "u_val": "dilated_gateway_location" } } ] + }, + { + "type": "effect_on_condition", + "id": "EOC_TELEPORT_dilated_gateway_SELECT_02", + "condition": { "math": [ "has_var(u_gateway_destination_2)" ] }, + "effect": [ { "set_string_var": "npc_gateway_destination_2", "target_var": { "u_val": "dilated_gateway_location" } } ] + }, + { + "type": "effect_on_condition", + "id": "EOC_TELEPORT_dilated_gateway_SELECT_03", + "condition": { "math": [ "has_var(u_gateway_destination_3)" ] }, + "effect": [ { "set_string_var": "npc_gateway_destination_3", "target_var": { "u_val": "dilated_gateway_location" } } ] + }, + { + "type": "effect_on_condition", + "id": "EOC_TELEPORT_dilated_gateway_SELECT_04", + "condition": { "math": [ "has_var(u_gateway_destination_4)" ] }, + "effect": [ { "set_string_var": "npc_gateway_destination_4", "target_var": { "u_val": "dilated_gateway_location" } } ] + }, + { + "type": "effect_on_condition", + "id": "EOC_TELEPORT_dilated_gateway_SELECT_05", + "condition": { "math": [ "has_var(u_gateway_destination_5)" ] }, + "effect": [ { "set_string_var": "npc_gateway_destination_5", "target_var": { "u_val": "dilated_gateway_location" } } ] + }, + { + "type": "effect_on_condition", + "id": "EOC_TELEPORT_dilated_gateway_SELECT_06", + "condition": { "math": [ "has_var(u_gateway_destination_6)" ] }, + "effect": [ { "set_string_var": "npc_gateway_destination_6", "target_var": { "u_val": "dilated_gateway_location" } } ] + }, + { + "type": "effect_on_condition", + "id": "EOC_TELEPORT_dilated_gateway_SELECT_07", + "condition": { "math": [ "has_var(u_gateway_destination_7)" ] }, + "effect": [ { "set_string_var": "npc_gateway_destination_7", "target_var": { "u_val": "dilated_gateway_location" } } ] + }, + { + "type": "effect_on_condition", + "id": "EOC_TELEPORT_dilated_gateway_SELECT_08", + "condition": { "math": [ "has_var(u_gateway_destination_8)" ] }, + "effect": [ { "set_string_var": "npc_gateway_destination_8", "target_var": { "u_val": "dilated_gateway_location" } } ] + }, + { + "type": "effect_on_condition", + "id": "EOC_TELEPORT_dilated_gateway_SELECT_09", + "condition": { "math": [ "has_var(u_gateway_destination_9)" ] }, + "effect": [ { "set_string_var": "npc_gateway_destination_9", "target_var": { "u_val": "dilated_gateway_location" } } ] + }, + { + "type": "effect_on_condition", + "id": "EOC_TELEPORT_dilated_gateway_SELECT_10", + "condition": { "math": [ "has_var(u_gateway_destination_10)" ] }, + "effect": [ { "set_string_var": "npc_gateway_destination_10", "target_var": { "u_val": "dilated_gateway_location" } } ] + }, { "type": "effect_on_condition", "id": "EOC_TELEPORT_SUMMON", @@ -785,5 +913,18 @@ "effect": [ { "u_spawn_monster": "GROUP_NETHER_BREACH", "group": true, "real_count": [ 2, 6 ], "min_radius": 2, "max_radius": 6 } ] + }, + { + "type": "effect_on_condition", + "id": "EOC_TELEPORT_LOCI_TECHNIQUE", + "condition": { "u_has_effect": "effect_teleport_loci_establishment" }, + "effect": [ + { + "u_teleport": { "u_val": "teleporter_loci_establishment_loc" }, + "success_message": "You feel a moment of darkness and terrible cold, but you are quickly back at your established locus.", + "fail_message": "Something goes wrong with the Loci Technique!" + } + ], + "false_effect": [ { "u_message": "You are currently not concentrating on [Ψ]Loci Establishment!" } ] } ] diff --git a/data/mods/MindOverMatter/recipes/practice/teleportation_practice.json b/data/mods/MindOverMatter/recipes/practice/teleportation_practice.json index 535710f58d182..d51f720b7a165 100644 --- a/data/mods/MindOverMatter/recipes/practice/teleportation_practice.json +++ b/data/mods/MindOverMatter/recipes/practice/teleportation_practice.json @@ -16,10 +16,14 @@ "practice_teleport_stride", "practice_teleport_transpose", "practice_teleport_displacement", + "practice_teleport_reactive_displacement", "practice_teleport_farstep", "practice_teleport_collapse", "practice_teleport_banish", + "practice_teleport_loci_establishment", + "practice_teleport_loci_technique", "practice_teleport_gateway", + "practice_teleport_dilated_gateway", "practice_teleport_breach", "practice_teleport_reality_tear" ], @@ -542,6 +546,97 @@ } ] }, + { + "type": "recipe", + "activity_level": "LIGHT_EXERCISE", + "name": "contemplation: reactive displacement", + "id": "practice_teleport_reactive_displacement", + "description": "Contemplate your powers and improve your ability to automatically teleport attackers away from you.", + "category": "CC_*", + "subcategory": "CSC_*_NESTED", + "skill_used": "metaphysics", + "difficulty": 5, + "time": "0 s", + "autolearn": false, + "proficiencies": [ { "proficiency": "prof_contemplation_teleportation", "required": false } ], + "tools": [ + [ [ "matrix_crystal_drained", -1 ], [ "black_nether_crystal_pseudo_tool", -1 ], [ "matrix_crystal_teleportation", -1 ] ] + ], + "components": [ [ [ "matrix_crystal_teleport_dust", 1 ] ] ], + "flags": [ "SECRET", "BLIND_EASY", "NO_MANIP", "AFFECTED_BY_PAIN", "NO_BENCH", "NO_ENCHANTMENT" ], + "result_eocs": [ + { + "id": "EOC_PRACTICE_TELEPORT_REACTIVE_DISPLACEMENT", + "condition": { "math": [ "u_spell_level('teleport_reactive_displacement') >= 1" ] }, + "effect": [ + { "set_string_var": "teleport_reactive_displacement", "target_var": { "u_val": "latest_studied_power_name" } }, + { + "set_string_var": "prof_contemplation_teleportation", + "target_var": { "u_val": "latest_studied_power_proficiency" } + }, + { "math": [ "u_latest_studied_power_difficulty = 5" ] }, + { "run_eocs": [ "EOC_PSI_STUDYING_POWER_BEGIN", "EOC_PSI_STUDYING_POWER_SIDE_EFFECTS" ] } + ], + "false_effect": [ + { "set_string_var": "teleport_reactive_displacement", "target_var": { "u_val": "latest_studied_power_name" } }, + { "u_message": "You attempt to unlock new capabilities within your mind." }, + { "u_assign_activity": "ACT_PSI_LEARNING_NEW_POWER", "duration": "16 hours" }, + { "u_add_effect": "effect_psi_learning_new_power", "duration": "16 hours" }, + { "run_eocs": "EOC_PSI_PRACTICE_FOCUS_MOD" }, + { + "run_eocs": "EOC_PRACTICE_TELEPORT_REACTIVE_DISPLACEMENT_LEARNING", + "time_in_future": [ { "math": [ "learn_new_power_lower_time_bound(5)" ] }, { "math": [ "learn_new_power_upper_time_bound(5)" ] } ] + } + ] + } + ] + }, + { + "type": "effect_on_condition", + "id": "EOC_PRACTICE_TELEPORT_REACTIVE_DISPLACEMENT_LEARNING", + "condition": { + "and": [ + { "compare_string": [ "teleport_reactive_displacement", { "u_val": "latest_studied_power_name" } ] }, + { "u_has_effect": "effect_psi_learning_new_power" }, + { + "not": { "u_has_any_effect": [ "sleep", "effect_vitakin_wakeful_resting", "lack_sleep", "sleep_deprived", "under_operation" ] } + } + ] + }, + "effect": [ + { + "run_eocs": [ + { + "id": "EOC_PRACTICE_TELEPORT_REACTIVE_DISPLACEMENT_LEARNING_2", + "condition": { + "and": [ + { + "roll_contested": { "math": [ "u_skill('metaphysics') + u_has_proficiency('prof_contemplation_teleportation')" ] }, + "difficulty": 10 + } + ] + }, + "effect": [ + { + "u_message": "As you meditate, all the pieces suddenly come together. You've unlocked: >.", + "popup": true + }, + { "math": [ "u_spell_level('teleport_reactive_displacement') = 1" ] }, + { "math": [ "u_vitamin('vitamin_psionic_drain')", "+=", "rng( 30,50 )" ] }, + { "u_lose_effect": "effect_psi_learning_new_power" }, + "u_cancel_activity" + ], + "false_effect": [ + { "u_message": "You just couldn't manage to grasp the technique. You'll have to try again.", "popup": true }, + { "math": [ "u_vitamin('vitamin_psionic_drain')", "+=", "rng( 30,50 )" ] }, + { "u_lose_effect": "effect_psi_learning_new_power" }, + "u_cancel_activity" + ] + } + ] + } + ] + }, { "type": "recipe", "activity_level": "LIGHT_EXERCISE", @@ -815,6 +910,134 @@ } ] }, + { + "type": "recipe", + "activity_level": "LIGHT_EXERCISE", + "name": "contemplation: loci establishment", + "id": "practice_teleport_loci_establishment", + "description": "Contemplate your powers and improve your ability to maintain an established locus that you can teleport to.", + "category": "CC_*", + "subcategory": "CSC_*_NESTED", + "skill_used": "metaphysics", + "difficulty": 6, + "time": "0 s", + "autolearn": false, + "proficiencies": [ { "proficiency": "prof_contemplation_teleportation", "required": false } ], + "tools": [ + [ [ "matrix_crystal_drained", -1 ], [ "black_nether_crystal_pseudo_tool", -1 ], [ "matrix_crystal_teleportation", -1 ] ] + ], + "components": [ [ [ "matrix_crystal_teleport_dust", 1 ] ] ], + "flags": [ "SECRET", "BLIND_EASY", "NO_MANIP", "AFFECTED_BY_PAIN", "NO_BENCH", "NO_ENCHANTMENT" ], + "result_eocs": [ + { + "id": "EOC_PRACTICE_TELEPORT_LOCI_ESTABLISHMENT", + "condition": { "math": [ "u_spell_level('teleport_loci_establishment') >= 1" ] }, + "effect": [ + { "set_string_var": "teleport_loci_establishment", "target_var": { "u_val": "latest_studied_power_name" } }, + { + "set_string_var": "prof_contemplation_teleportation", + "target_var": { "u_val": "latest_studied_power_proficiency" } + }, + { "math": [ "u_latest_studied_power_difficulty = 6" ] }, + { "run_eocs": [ "EOC_PSI_STUDYING_POWER_BEGIN", "EOC_PSI_STUDYING_POWER_SIDE_EFFECTS" ] } + ], + "false_effect": [ + { "set_string_var": "teleport_loci_establishment", "target_var": { "u_val": "latest_studied_power_name" } }, + { "u_message": "You attempt to unlock new capabilities within your mind." }, + { "u_assign_activity": "ACT_PSI_LEARNING_NEW_POWER", "duration": "16 hours" }, + { "u_add_effect": "effect_psi_learning_new_power", "duration": "16 hours" }, + { "run_eocs": "EOC_PSI_PRACTICE_FOCUS_MOD" }, + { + "run_eocs": "EOC_PRACTICE_TELEPORT_LOCI_ESTABLISHMENT_LEARNING", + "time_in_future": [ { "math": [ "learn_new_power_lower_time_bound(6)" ] }, { "math": [ "learn_new_power_upper_time_bound(6)" ] } ] + } + ] + } + ] + }, + { + "type": "effect_on_condition", + "id": "EOC_PRACTICE_TELEPORT_LOCI_ESTABLISHMENT_LEARNING", + "condition": { + "and": [ + { "compare_string": [ "teleport_loci_establishment", { "u_val": "latest_studied_power_name" } ] }, + { "u_has_effect": "effect_psi_learning_new_power" }, + { + "not": { "u_has_any_effect": [ "sleep", "effect_vitakin_wakeful_resting", "lack_sleep", "sleep_deprived", "under_operation" ] } + } + ] + }, + "effect": [ + { + "run_eocs": [ + { + "id": "EOC_PRACTICE_TELEPORT_LOCI_ESTABLISHMENT_LEARNING_2", + "condition": { + "and": [ + { + "roll_contested": { "math": [ "u_skill('metaphysics') + u_has_proficiency('prof_contemplation_teleportation')" ] }, + "difficulty": 10 + } + ] + }, + "effect": [ + { + "u_message": "As you meditate, all the pieces suddenly come together. You've unlocked: >.", + "popup": true + }, + { "math": [ "u_spell_level('teleport_loci_establishment') = 1" ] }, + { "math": [ "u_spell_level('teleport_loci_technique') = 1" ] }, + { "u_learn_recipe": "practice_teleport_loci_technique" }, + { "math": [ "u_vitamin('vitamin_psionic_drain')", "+=", "rng( 35,70 )" ] }, + { "u_lose_effect": "effect_psi_learning_new_power" }, + "u_cancel_activity" + ], + "false_effect": [ + { "u_message": "You just couldn't manage to grasp the technique. You'll have to try again.", "popup": true }, + { "math": [ "u_vitamin('vitamin_psionic_drain')", "+=", "rng( 35,70 )" ] }, + { "u_lose_effect": "effect_psi_learning_new_power" }, + "u_cancel_activity" + ] + } + ] + } + ] + }, + { + "type": "recipe", + "activity_level": "LIGHT_EXERCISE", + "name": "contemplation: loci technique", + "id": "practice_teleport_loci_technique", + "description": "Contemplate your powers and improve your ability to travel to an established locus.", + "category": "CC_*", + "subcategory": "CSC_*_NESTED", + "skill_used": "metaphysics", + "difficulty": 6, + "time": "0 s", + "autolearn": false, + "proficiencies": [ { "proficiency": "prof_contemplation_teleportation", "required": false } ], + "tools": [ + [ [ "matrix_crystal_drained", -1 ], [ "black_nether_crystal_pseudo_tool", -1 ], [ "matrix_crystal_teleportation", -1 ] ] + ], + "components": [ [ [ "matrix_crystal_teleport_dust", 1 ] ] ], + "flags": [ "SECRET", "BLIND_EASY", "NO_MANIP", "AFFECTED_BY_PAIN", "NO_BENCH", "NO_ENCHANTMENT" ], + "result_eocs": [ + { + "id": "EOC_PRACTICE_TELEPORT_LOCI_TECHNIQUET", + "//": "EOC is intentionally missing false effect since the loci technique power is learned via the loci establishment EOC rather than on its own.", + "condition": { "math": [ "u_spell_level('teleport_loci_technique') >= 1" ] }, + "effect": [ + { "set_string_var": "teleport_loci_technique", "target_var": { "u_val": "latest_studied_power_name" } }, + { + "set_string_var": "prof_contemplation_teleportation", + "target_var": { "u_val": "latest_studied_power_proficiency" } + }, + { "math": [ "u_latest_studied_power_difficulty = 6" ] }, + { "run_eocs": [ "EOC_PSI_STUDYING_POWER_BEGIN", "EOC_PSI_STUDYING_POWER_SIDE_EFFECTS" ] } + ] + } + ] + }, { "type": "recipe", "activity_level": "LIGHT_EXERCISE", @@ -906,6 +1129,97 @@ } ] }, + { + "type": "recipe", + "activity_level": "LIGHT_EXERCISE", + "name": "contemplation: dilated gateway", + "id": "practice_teleport_dilated_gateway", + "description": "Contemplate your powers and improve your ability to teleport other creatures with you to long-distant points.", + "category": "CC_*", + "subcategory": "CSC_*_NESTED", + "skill_used": "metaphysics", + "difficulty": 8, + "time": "0 s", + "autolearn": false, + "proficiencies": [ { "proficiency": "prof_contemplation_teleportation", "required": false } ], + "tools": [ + [ [ "matrix_crystal_drained", -1 ], [ "black_nether_crystal_pseudo_tool", -1 ], [ "matrix_crystal_teleportation", -1 ] ] + ], + "components": [ [ [ "matrix_crystal_teleport_dust", 1 ] ] ], + "flags": [ "SECRET", "BLIND_EASY", "NO_MANIP", "AFFECTED_BY_PAIN", "NO_BENCH", "NO_ENCHANTMENT" ], + "result_eocs": [ + { + "id": "EOC_PRACTICE_TELEPORT_dilated_gateway", + "condition": { "math": [ "u_spell_level('teleport_dilated_gateway') >= 1" ] }, + "effect": [ + { "set_string_var": "teleport_dilated_gateway", "target_var": { "u_val": "latest_studied_power_name" } }, + { + "set_string_var": "prof_contemplation_teleportation", + "target_var": { "u_val": "latest_studied_power_proficiency" } + }, + { "math": [ "u_latest_studied_power_difficulty = 9" ] }, + { "run_eocs": [ "EOC_PSI_STUDYING_POWER_BEGIN", "EOC_PSI_STUDYING_POWER_SIDE_EFFECTS" ] } + ], + "false_effect": [ + { "set_string_var": "teleport_dilated_gateway", "target_var": { "u_val": "latest_studied_power_name" } }, + { "u_message": "You attempt to unlock new capabilities within your mind." }, + { "u_assign_activity": "ACT_PSI_LEARNING_NEW_POWER", "duration": "16 hours" }, + { "u_add_effect": "effect_psi_learning_new_power", "duration": "16 hours" }, + { "run_eocs": "EOC_PSI_PRACTICE_FOCUS_MOD" }, + { + "run_eocs": "EOC_PRACTICE_TELEPORT_dilated_gateway_LEARNING", + "time_in_future": [ { "math": [ "learn_new_power_lower_time_bound(9)" ] }, { "math": [ "learn_new_power_upper_time_bound(9)" ] } ] + } + ] + } + ] + }, + { + "type": "effect_on_condition", + "id": "EOC_PRACTICE_TELEPORT_dilated_gateway_LEARNING", + "condition": { + "and": [ + { "compare_string": [ "teleport_dilated_gateway", { "u_val": "latest_studied_power_name" } ] }, + { "u_has_effect": "effect_psi_learning_new_power" }, + { + "not": { "u_has_any_effect": [ "sleep", "effect_vitakin_wakeful_resting", "lack_sleep", "sleep_deprived", "under_operation" ] } + } + ] + }, + "effect": [ + { + "run_eocs": [ + { + "id": "EOC_PRACTICE_TELEPORT_dilated_gateway_LEARNING_2", + "condition": { + "and": [ + { + "roll_contested": { "math": [ "u_skill('metaphysics') + u_has_proficiency('prof_contemplation_teleportation')" ] }, + "difficulty": 13 + } + ] + }, + "effect": [ + { + "u_message": "As you meditate, all the pieces suddenly come together. You've unlocked: >.", + "popup": true + }, + { "math": [ "u_spell_level('teleport_dilated_gateway') = 1" ] }, + { "math": [ "u_vitamin('vitamin_psionic_drain')", "+=", "rng( 45,90 )" ] }, + { "u_lose_effect": "effect_psi_learning_new_power" }, + "u_cancel_activity" + ], + "false_effect": [ + { "u_message": "You just couldn't manage to grasp the technique. You'll have to try again.", "popup": true }, + { "math": [ "u_vitamin('vitamin_psionic_drain')", "+=", "rng( 45,90 )" ] }, + { "u_lose_effect": "effect_psi_learning_new_power" }, + "u_cancel_activity" + ] + } + ] + } + ] + }, { "type": "recipe", "activity_level": "LIGHT_EXERCISE", diff --git a/doc/EFFECT_ON_CONDITION.md b/doc/EFFECT_ON_CONDITION.md index 0cbdce03795bf..386ab6ee07bed 100644 --- a/doc/EFFECT_ON_CONDITION.md +++ b/doc/EFFECT_ON_CONDITION.md @@ -4022,6 +4022,7 @@ You or NPC is teleported to `target_var` coordinates | "success_message" | optional | string or [variable object](#variable-object) | message, that would be printed, if teleportation was successful | | "fail_message" | optional | string or [variable object](#variable-object) | message, that would be printed, if teleportation was failed, like if coordinates contained creature or impassable obstacle (like wall) | | "force" | optional | boolean | default false; if true, teleportation can't fail - any creature, that stand on target coordinates, would be brutally telefragged, and if impassable obstacle occur, the closest point would be picked instead | +| "force_safe" | optional | boolean | default false; if true, teleportation cannot^(tm) fail. If there is a creature or obstacle at the target coordinate, the closest passable point within 5 horizontal tiles is picked instead. If there is no point, the creature remains where they are. ##### Valid talkers: diff --git a/src/npctalk.cpp b/src/npctalk.cpp index f4c3d8d67f223..421fa2b6beb65 100644 --- a/src/npctalk.cpp +++ b/src/npctalk.cpp @@ -7024,12 +7024,14 @@ talk_effect_fun_t::func f_teleport( const JsonObject &jo, std::string_view membe success_message.str_val = translation(); } bool force = jo.get_bool( "force", false ); - return [is_npc, target_var, fail_message, success_message, force]( dialogue const & d ) { + bool force_safe = jo.get_bool( "force_safe", false ); + return [is_npc, target_var, fail_message, success_message, force, + force_safe]( dialogue const & d ) { tripoint_abs_ms target_pos = get_tripoint_from_var( target_var, d, is_npc ); Creature *teleporter = d.actor( is_npc )->get_creature(); if( teleporter ) { if( teleport::teleport_to_point( *teleporter, get_map().bub_from_abs( target_pos ), true, false, - false, force ) ) { + false, force, force_safe ) ) { teleporter->add_msg_if_player( success_message.evaluate( d ) ); } else { teleporter->add_msg_if_player( fail_message.evaluate( d ) ); diff --git a/src/teleport.cpp b/src/teleport.cpp index 9798cf4651809..7cebd47dc3fc3 100644 --- a/src/teleport.cpp +++ b/src/teleport.cpp @@ -53,7 +53,7 @@ bool teleport::teleport( Creature &critter, int min_distance, int max_distance, } bool teleport::teleport_to_point( Creature &critter, tripoint_bub_ms target, bool safe, - bool add_teleglow, bool display_message, bool force ) + bool add_teleglow, bool display_message, bool force, bool force_safe ) { if( critter.pos_bub() == target ) { return false; @@ -68,9 +68,9 @@ bool teleport::teleport_to_point( Creature &critter, tripoint_bub_ms target, boo return false; } //The teleportee is dimensionally anchored so nothing happens - if( !force && p && ( p->worn_with_flag( json_flag_DIMENSIONAL_ANCHOR ) || - p->has_effect_with_flag( json_flag_DIMENSIONAL_ANCHOR ) || - p->has_effect_with_flag( json_flag_TELEPORT_LOCK ) ) ) { + if( !force && !force_safe && p && ( p->worn_with_flag( json_flag_DIMENSIONAL_ANCHOR ) || + p->has_effect_with_flag( json_flag_DIMENSIONAL_ANCHOR ) || + p->has_effect_with_flag( json_flag_TELEPORT_LOCK ) ) ) { if( display_message ) { p->add_msg_if_player( m_warning, _( "You feel a strange, inwards force." ) ); } @@ -94,7 +94,7 @@ bool teleport::teleport_to_point( Creature &critter, tripoint_bub_ms target, boo } //handles teleporting into solids. if( dest->impassable( dest_target ) ) { - if( force ) { + if( force || force_safe ) { std::vector nearest_points = closest_points_first( dest_target, 5 ); nearest_points.erase( nearest_points.begin() ); //TODO: Swap for this once #75961 merges @@ -131,73 +131,106 @@ bool teleport::teleport_to_point( Creature &critter, tripoint_bub_ms target, boo int tfrag_attempts = 5; bool collision = false; int collision_angle = 0; - while( Creature *const poor_soul = get_creature_tracker().creature_at( abs_ms ) ) { - //Fail if we run out of telefrag attempts - if( tfrag_attempts-- < 1 ) { - if( p && display_message ) { - p->add_msg_player_or_npc( m_warning, _( "You flicker." ), _( " flickers." ) ); - } else if( get_player_view().sees( critter ) && display_message ) { - add_msg( _( "%1$s flickers." ), critter.disp_name() ); + + if( force_safe ) { + // creature_at doesn't seem to function for NPCs when teleporting far distances. + if( get_creature_tracker().creature_at( abs_ms ) != nullptr ) { + bool found_new_spot = false; + std::vector nearest_points = closest_points_first( abs_ms, 5 ); + nearest_points.erase( nearest_points.begin() ); + //TODO: Swap for this once #75961 merges + //std::vector nearest_points = closest_points_first( abs_ms, 1, 5 ); + + // get nearest safe point and teleport there instead + for( tripoint_abs_ms p : nearest_points ) { + // If point is not inbounds, ignore if spot is passible or not. Creatures in impassable terrain will be automatically teleported out in their turn. + // some way of validating terrain passability out of bounds would be superior, however. + if( ( !dest->inbounds( here.bub_from_abs( p ) ) || dest->passable( here.bub_from_abs( p ) ) ) && + get_creature_tracker().creature_at( p ) == nullptr ) { + found_new_spot = true; + abs_ms = p; + target = here.bub_from_abs( p ); + break; + } + } + if( !found_new_spot ) { + if( c_is_u && display_message ) { + add_msg( m_bad, _( "You cannot teleport safely." ) ); + } else if( !c_is_u && p != nullptr ) { + add_msg( m_bad, _( "%s flickers but remains exactly where they are." ), p->get_name() ); + } + return false; } - return false; - } - //if the thing that was going to be teleported into has a dimensional anchor, break out early and don't teleport. - if( poor_soul->as_character() && - ( poor_soul->as_character()->worn_with_flag( json_flag_DIMENSIONAL_ANCHOR ) || - poor_soul->as_character()->has_effect_with_flag( json_flag_DIMENSIONAL_ANCHOR ) ) ) { - poor_soul->as_character()->add_msg_if_player( m_warning, _( "You feel disjointed." ) ); - return false; } - if( force ) { - //this should only happen through debug menu, so this won't affect the player. - poor_soul->apply_damage( nullptr, bodypart_id( "torso" ), 9999 ); - poor_soul->check_dead_state(); - } else if( safe ) { - if( c_is_u && display_message ) { - add_msg( m_bad, _( "You cannot teleport safely." ) ); + } else { + while( Creature *const poor_soul = get_creature_tracker().creature_at( abs_ms ) ) { + //Fail if we run out of telefrag attempts + if( tfrag_attempts-- < 1 ) { + if( p && display_message ) { + p->add_msg_player_or_npc( m_warning, _( "You flicker." ), _( " flickers." ) ); + } else if( get_player_view().sees( critter ) && display_message ) { + add_msg( _( "%1$s flickers." ), critter.disp_name() ); + } + return false; } - return false; - } else if( !collision ) { - //we passed all the conditions needed for a teleport accident, so handle messages for teleport accidents here - const bool poor_soul_is_u = poor_soul->is_avatar(); - if( poor_soul_is_u && display_message ) { - add_msg( m_bad, _( "You're blasted with strange energy!" ) ); + //if the thing that was going to be teleported into has a dimensional anchor, break out early and don't teleport. + if( poor_soul->as_character() && + ( poor_soul->as_character()->worn_with_flag( json_flag_DIMENSIONAL_ANCHOR ) || + poor_soul->as_character()->has_effect_with_flag( json_flag_DIMENSIONAL_ANCHOR ) ) ) { + poor_soul->as_character()->add_msg_if_player( m_warning, _( "You feel disjointed." ) ); + return false; } - if( p ) { - if( display_message ) { - p->add_msg_player_or_npc( m_warning, - _( "You collide with %s mid teleport, and you are both knocked away by a violent explosion of energy." ), - _( " collides with %s mid teleport, and they are both knocked away by a violent explosion of energy." ), - poor_soul->disp_name() ); + if( force ) { + //this should only happen through debug menu, so this won't affect the player. + poor_soul->apply_damage( nullptr, bodypart_id( "torso" ), 9999 ); + poor_soul->check_dead_state(); + } else if( safe ) { + if( c_is_u && display_message ) { + add_msg( m_bad, _( "You cannot teleport safely." ) ); + } + return false; + } else if( !collision ) { + //we passed all the conditions needed for a teleport accident, so handle messages for teleport accidents here + const bool poor_soul_is_u = poor_soul->is_avatar(); + if( poor_soul_is_u && display_message ) { + add_msg( m_bad, _( "You're blasted with strange energy!" ) ); } - } else { - if( get_player_view().sees( *poor_soul ) ) { + if( p ) { if( display_message ) { - add_msg( m_warning, - _( "%1$s collides with %2$s mid teleport, and they are both knocked away by a violent explosion of energy!" ), - critter.disp_name(), poor_soul->disp_name() ); + p->add_msg_player_or_npc( m_warning, + _( "You collide with %s mid teleport, and you are both knocked away by a violent explosion of energy." ), + _( " collides with %s mid teleport, and they are both knocked away by a violent explosion of energy." ), + poor_soul->disp_name() ); } + } else { + if( get_player_view().sees( *poor_soul ) ) { + if( display_message ) { + add_msg( m_warning, + _( "%1$s collides with %2$s mid teleport, and they are both knocked away by a violent explosion of energy!" ), + critter.disp_name(), poor_soul->disp_name() ); + } + } + //once collision this if block shouldn't run so everything here should only happen once + collision = true; + //determine a random angle to throw the thing it teleported into, then fling it. + collision_angle = rng( 0, 360 ); + g->fling_creature( poor_soul, units::from_degrees( collision_angle - 180 ), 40, false, true ); + //spawn a mostly cosmetic explosion for flair. + explosion_handler::explosion( &critter, target, 10 ); + //if it was grabbed, it isn't anymore. + for( const effect &grab : poor_soul->get_effects_with_flag( json_flag_GRAB ) ) { + poor_soul->remove_effect( grab.get_id() ); + } + //apply a bunch of damage to it + std::vector target_bdpts = poor_soul->get_all_body_parts( + get_body_part_flags::only_main ); + for( const bodypart_id &bp_id : target_bdpts ) { + const float damage_to_deal = + static_cast( poor_soul->get_part_hp_max( bp_id ) ) / static_cast( rng( 6, 12 ) ); + poor_soul->apply_damage( nullptr, bp_id, damage_to_deal ); + } + poor_soul->check_dead_state(); } - //once collision this if block shouldn't run so everything here should only happen once - collision = true; - //determine a random angle to throw the thing it teleported into, then fling it. - collision_angle = rng( 0, 360 ); - g->fling_creature( poor_soul, units::from_degrees( collision_angle - 180 ), 40, false, true ); - //spawn a mostly cosmetic explosion for flair. - explosion_handler::explosion( &critter, target, 10 ); - //if it was grabbed, it isn't anymore. - for( const effect &grab : poor_soul->get_effects_with_flag( json_flag_GRAB ) ) { - poor_soul->remove_effect( grab.get_id() ); - } - //apply a bunch of damage to it - std::vector target_bdpts = poor_soul->get_all_body_parts( - get_body_part_flags::only_main ); - for( const bodypart_id &bp_id : target_bdpts ) { - const float damage_to_deal = - static_cast( poor_soul->get_part_hp_max( bp_id ) ) / static_cast( rng( 6, 12 ) ); - poor_soul->apply_damage( nullptr, bp_id, damage_to_deal ); - } - poor_soul->check_dead_state(); } } } @@ -227,5 +260,6 @@ bool teleport::teleport_to_point( Creature &critter, tripoint_bub_ms target, boo for( const effect &grab : critter.get_effects_with_flag( json_flag_GRAB ) ) { critter.remove_effect( grab.get_id() ); } + return true; } diff --git a/src/teleport.h b/src/teleport.h index 265bfa85c7c6b..3a82021688bc1 100644 --- a/src/teleport.h +++ b/src/teleport.h @@ -14,7 +14,7 @@ namespace teleport bool teleport( Creature &critter, int min_distance = 2, int max_distance = 12, bool safe = false, bool add_teleglow = true ); bool teleport_to_point( Creature &critter, tripoint_bub_ms target, bool safe, bool add_teleglow, - bool display_message = true, bool force = false ); + bool display_message = true, bool force = false, bool force_safe = false ); } // namespace teleport #endif // CATA_SRC_TELEPORT_H diff --git a/tools/spell_checker/dictionary.txt b/tools/spell_checker/dictionary.txt index a003f24c41c48..74f918f64e535 100644 --- a/tools/spell_checker/dictionary.txt +++ b/tools/spell_checker/dictionary.txt @@ -994,6 +994,7 @@ Cassidy Cassiopeia castable Castanea +casted Casterbridge Casull cataphract