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

[Magiclysm] Attunements - Rock Blast spell #44682

Merged
merged 3 commits into from
Oct 8, 2020
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
51 changes: 51 additions & 0 deletions data/mods/Magiclysm/Spells/attunements/Earth_Elemental.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,56 @@
"max_aoe": 35,
"aoe_increment": 1,
"max_level": 35
},
{
"id": "rock_blast",
"type": "SPELL",
"description": "Fire three large rocks at an enemy, causing blunt damage and knocking it back.",
"valid_targets": [ "hostile" ],
"flags": [ "SOMATIC", "NO_LEGS" ],
"effect": "attack",
"shape": "blast",
"max_level": 35,
"min_damage": 20,
"max_damage": 180,
"damage_increment": 4.6,
"min_range": 8,
"max_range": 15,
"range_increment": 0.2,
"sound_id": "earth_spell",
"sound_variant": "strong",
"energy_source": "STAMINA",
"spell_class": "EARTH_ELEMENTAL",
"damage_type": "bash",
"base_energy_cost": 5000,
"base_casting_time": 200,
"extra_effects": [ { "id": "single_rock_blast" }, { "id": "single_rock_blast" }, { "id": "rock_blast_push" } ]
},
{
"id": "single_rock_blast",
"type": "SPELL",
"description": "A single portion of the rock blast spell",
"valid_targets": [ "hostile" ],
"effect": "attack",
"shape": "blast",
"max_level": 35,
"min_damage": 20,
"max_damage": 180,
"damage_increment": 4.6,
"damage_type": "bash",
"sound_id": "earth_spell",
"sound_variant": "strong"
},
{
"id": "rock_blast_push",
"type": "SPELL",
"description": "The push portion of the rock blast spell",
"valid_targets": [ "hostile" ],
"effect": "directed_push",
"shape": "blast",
"max_level": 35,
"min_damage": 1,
"max_damage": 3,
"damage_increment": 0.1
}
]
32 changes: 32 additions & 0 deletions data/mods/Magiclysm/Spells/debug.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,38 @@
"//7": "Learn spells by adding map of 'spell_id': 'level' ",
"learn_spells": { "create_atomic_light": 1, "megablast": 2 }
},
{
"type": "SPELL",
"id": "debug_push_basic",
"name": "debug push no aoe",
"description": "pushes all types of objects with an aoe of 0",
"valid_targets": [ "ally", "self", "hostile", "field", "item", "ground" ],
"effect": "directed_push",
"shape": "blast",
"min_damage": 0,
"max_damage": 10,
"damage_increment": 1,
"min_range": 20,
"max_range": 20,
"max_level": 10
},
{
"type": "SPELL",
"id": "debug_push_blast",
"name": "debug push blast",
"description": "pushes all types of objects with an aoe of 3 in a blast pattern",
"valid_targets": [ "ally", "self", "hostile", "field", "item", "ground" ],
"effect": "directed_push",
"shape": "blast",
"min_aoe": 3,
"max_aoe": 3,
"min_damage": 0,
"max_damage": 10,
"damage_increment": 1,
"min_range": 20,
"max_range": 20,
"max_level": 10
},
{
"id": "spawn_debug_monster",
"type": "SPELL",
Expand Down
2 changes: 1 addition & 1 deletion data/mods/Magiclysm/traits/attunements.json
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@
"valid": false,
"description": "Stone is superior to flesh. You have allowed this axiom into your life, and work to correct your own weakness with biomancy. The strength of the Earth rushed up to meet you with open arms.",
"prereqs": [ "BIOMANCER", "EARTHSHAPER" ],
"spells_learned": [ [ "quake", 5 ] ],
"spells_learned": [ [ "quake", 5 ], [ "rock_blast", 5 ] ],
"armor": [
{ "parts": [ "torso", "arm_l", "arm_r", "hand_l", "hand_r", "leg_l", "leg_r", "foot_l", "foot_r", "head" ], "cut": 15 }
],
Expand Down
1 change: 1 addition & 0 deletions src/magic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ void spell_type::load( const JsonObject &jo, const std::string & )
{ "translocate", spell_effect::translocate },
{ "area_pull", spell_effect::area_pull },
{ "area_push", spell_effect::area_push },
{ "directed_push", spell_effect::directed_push },
{ "timed_event", spell_effect::timed_event },
{ "ter_transform", spell_effect::transform_blast },
{ "noise", spell_effect::noise },
Expand Down
1 change: 1 addition & 0 deletions src/magic.h
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,7 @@ void targeted_polymorph( const spell &sp, Creature &caster, const tripoint &targ

void area_pull( const spell &sp, Creature &caster, const tripoint &center );
void area_push( const spell &sp, Creature &caster, const tripoint &center );
void directed_push( const spell &sp, Creature &caster, const tripoint &target );

std::set<tripoint> spell_effect_blast( const override_parameters &params, const tripoint &,
const tripoint &target );
Expand Down
154 changes: 134 additions & 20 deletions src/magic_spell_effect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#include "monster.h"
#include "monstergenerator.h"
#include "mtype.h"
#include "npc.h"
#include "optional.h"
#include "overmapbuffer.h"
#include "pimpl.h"
Expand Down Expand Up @@ -654,6 +655,30 @@ void area_expander::sort_descending()
} );
}

static void move_items( map &here, const tripoint &from, const tripoint &to )
{
for( const item &it : here.i_at( from ) ) {
here.add_item( to, it );
}
here.i_clear( from );
}

static void move_field( map &here, const tripoint &from, const tripoint &to )
{
field &src_field = here.field_at( from );
std::map<field_type_id, int> moving_fields;
for( const std::pair<const field_type_id, field_entry> &fd : src_field ) {
if( fd.first.is_valid() && !fd.first.id().is_null() ) {
const int intensity = fd.second.get_field_intensity();
moving_fields.emplace( fd.first, intensity );
}
}
for( const std::pair<const field_type_id, int> &fd : moving_fields ) {
here.remove_field( from, fd.first );
here.set_field_intensity( to, fd.first, fd.second );
}
}

// Moving all objects from one point to another by the power of magic.
static void spell_move( const spell &sp, const Creature &caster,
const tripoint &from, const tripoint &to )
Expand Down Expand Up @@ -686,30 +711,12 @@ static void spell_move( const spell &sp, const Creature &caster,

// Moving items
if( sp.is_valid_target( spell_target::item ) ) {
map &here = get_map();
map_stack src_items = here.i_at( from );
map_stack dst_items = here.i_at( to );
for( const item &item : src_items ) {
dst_items.insert( item );
}
src_items.clear();
move_items( get_map(), from, to );
}

// Moving fields.
if( sp.is_valid_target( spell_target::field ) ) {
map &here = get_map();
field &src_field = here.field_at( from );
std::map<field_type_id, int> moving_fields;
for( const std::pair<const field_type_id, field_entry> &fd : src_field ) {
if( fd.first.is_valid() && !fd.first.id().is_null() ) {
const int intensity = fd.second.get_field_intensity();
moving_fields.emplace( fd.first, intensity );
}
}
for( const std::pair<const field_type_id, int> &fd : moving_fields ) {
here.remove_field( from, fd.first );
here.set_field_intensity( to, fd.first, fd.second );
}
move_field( get_map(), from, to );
}
}

Expand Down Expand Up @@ -749,6 +756,113 @@ void spell_effect::area_push( const spell &sp, Creature &caster, const tripoint
sp.make_sound( caster.pos() );
}

static void character_push_effects( Creature *caster, Character &guy, tripoint &push_dest,
const int push_distance, const std::vector<tripoint> &push_vec )
{
int dist_left = std::abs( push_distance );
for( const tripoint &pushed_point : push_vec ) {
if( get_map().impassable( pushed_point ) ) {
guy.hurtall( dist_left * 4, caster );
push_dest = pushed_point;
break;
} else {
dist_left--;
}
}
guy.setpos( push_dest );
}

void spell_effect::directed_push( const spell &sp, Creature &caster, const tripoint &target )
{
std::set<tripoint> area = spell_effect_area( sp, target, caster );
// this group of variables is for deferring movement of the avatar
int pushed_distance;
tripoint push_to;
std::vector<tripoint> pushed_vec;
bool player_pushed = false;

::map &here = get_map();

// whether it's push or pull, so how the multimap is sorted
// -1 is push and 1 is pull
const int sign = sp.damage() > 0 ? -1 : 1;

std::multimap<int, tripoint> targets_ordered_by_range;
for( const tripoint &pt : area ) {
targets_ordered_by_range.emplace( sign * rl_dist( pt, caster.pos() ), pt );
}

for( const std::pair<int, tripoint> &pair : targets_ordered_by_range ) {
const tripoint &push_point = pair.second;
const int angle = coord_to_angle( caster.pos(), target );
// positive is push, negative is pull
int push_distance = sp.damage();
const int prev_distance = rl_dist( caster.pos(), target );
if( push_distance < 0 ) {
push_distance = std::max( -std::abs( push_distance ), -std::abs( prev_distance ) );
}
if( push_distance == 0 ) {
continue;
}

tripoint push_dest;
calc_ray_end( angle, push_distance, push_point, push_dest );
const std::vector<tripoint> push_vec = line_to( push_point, push_dest );

const Creature *critter = g->critter_at<Creature>( push_point );
if( critter != nullptr ) {
const Creature::Attitude attitude_to_target =
caster.attitude_to( *g->critter_at<Creature>( push_point ) );

monster *mon = g->critter_at<monster>( push_point );
npc *guy = g->critter_at<npc>( push_point );

if( ( sp.is_valid_target( spell_target::self ) && push_point == caster.pos() ) ||
( attitude_to_target == Creature::Attitude::FRIENDLY &&
sp.is_valid_target( spell_target::ally ) ) ||
( ( attitude_to_target == Creature::Attitude::HOSTILE ||
attitude_to_target == Creature::Attitude::NEUTRAL ) &&
sp.is_valid_target( spell_target::hostile ) ) ) {
if( g->critter_at<avatar>( push_point ) ) {
// defer this because this absolutely must be done last in order not to mess up our calculations
player_pushed = true;
pushed_distance = push_distance;
push_to = push_dest;
pushed_vec = push_vec;
} else if( mon ) {
int dist_left = std::abs( push_distance );
for( const tripoint &pushed_push_point : push_vec ) {
if( get_map().impassable( pushed_push_point ) ) {
mon->apply_damage( &caster, bodypart_id(), dist_left * 10 );
push_dest = pushed_push_point;
break;
} else {
dist_left--;
}
}
mon->setpos( push_dest );
} else if( guy ) {
character_push_effects( &caster, *guy, push_dest, push_distance, push_vec );
}
}
}

if( sp.is_valid_target( spell_target::item ) && here.has_items( push_point ) ) {
move_items( here, push_point, push_dest );
}


if( sp.is_valid_target( spell_target::field ) ) {
move_field( here, push_point, push_dest );
}
}

// deferred avatar pushing
if( player_pushed ) {
character_push_effects( &caster, get_avatar(), push_to, pushed_distance, pushed_vec );
}
}

void spell_effect::spawn_ethereal_item( const spell &sp, Creature &caster, const tripoint & )
{
item granted( sp.effect_data(), calendar::turn );
Expand Down