Skip to content

Commit

Permalink
Rework and unify teleporting
Browse files Browse the repository at this point in the history
  • Loading branch information
John-Candlebury committed Sep 24, 2019
1 parent bca29b6 commit 17d7ff2
Show file tree
Hide file tree
Showing 13 changed files with 130 additions and 110 deletions.
3 changes: 2 additions & 1 deletion src/bionics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
#include "item_location.h"
#include "monster.h"
#include "point.h"
#include "teleport.h"

const skill_id skilll_electronics( "electronics" );
const skill_id skilll_firstaid( "firstaid" );
Expand Down Expand Up @@ -383,7 +384,7 @@ bool player::activate_bionic( int b, bool eff_only )
add_msg_if_player( m_info, _( "You cannot activate that while mounted." ) );
return false;
}
g->teleport();
teleport::teleport( this );
add_effect( effect_teleglow, 30_minutes );
mod_moves( -100 );
} else if( bio.id == "bio_blood_anal" ) {
Expand Down
55 changes: 0 additions & 55 deletions src/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11035,61 +11035,6 @@ void game::perhaps_add_random_npc()
load_npcs();
}

void game::teleport( player *p, bool add_teleglow )
{
if( p == nullptr ) {
p = &u;
}
int tries = 0;
tripoint new_pos = p->pos();
bool is_u = ( p == &u );

if( add_teleglow ) {
p->add_effect( effect_teleglow, 30_minutes );
}
do {
new_pos.x = p->posx() + rng( 0, SEEX * 2 ) - SEEX;
new_pos.y = p->posy() + rng( 0, SEEY * 2 ) - SEEY;
tries++;
} while( tries < 15 && m.impassable( new_pos ) );
bool can_see = ( is_u || u.sees( new_pos ) );
if( p->in_vehicle ) {
m.unboard_vehicle( p->pos() );
}
p->setx( new_pos.x );
p->sety( new_pos.y );
if( m.impassable( new_pos ) ) { //Teleported into a wall
const std::string obstacle_name = m.obstacle_name( new_pos );
g->events().send<event_type::teleports_into_wall>( p->getID(), obstacle_name );
if( can_see ) {
if( is_u ) {
add_msg( _( "You teleport into the middle of a %s!" ),
m.obstacle_name( new_pos ) );
} else {
add_msg( _( "%1$s teleports into the middle of a %2$s!" ),
p->name, m.obstacle_name( new_pos ) );
}
}
p->apply_damage( nullptr, bp_torso, 500 );
p->check_dead_state();
} else if( monster *const mon_ptr = critter_at<monster>( new_pos ) ) {
g->events().send<event_type::telefrags_creature>( p->getID(), mon_ptr->name() );
if( can_see ) {
if( is_u ) {
add_msg( _( "You teleport into the middle of a %s!" ),
mon_ptr->name() );
} else {
add_msg( _( "%1$s teleports into the middle of a %2$s!" ),
p->name, mon_ptr->name() );
}
mon_ptr->die_in_explosion( p );
}
}
if( is_u ) {
update_map( *p );
}
}

void game::display_scent()
{
if( use_tiles ) {
Expand Down
2 changes: 0 additions & 2 deletions src/game.h
Original file line number Diff line number Diff line change
Expand Up @@ -454,8 +454,6 @@ class game
void validate_camps();
/** process vehicles that are following the player */
void following_vehicles();
/** Performs a random short-distance teleport on the given player, granting teleglow if needed. */
void teleport( player *p = nullptr, bool add_teleglow = true );
/** Picks and spawns a random fish from the remaining fish list when a fish is caught. */
void catch_a_monster( monster *fish, const tripoint &pos, player *p,
const time_duration &catch_duration );
Expand Down
5 changes: 3 additions & 2 deletions src/iuse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
#include "item_group.h"
#include "omdata.h"
#include "point.h"
#include "teleport.h"

#define RADIO_PER_TURN 25 // how many characters per turn of radio

Expand Down Expand Up @@ -3431,7 +3432,7 @@ int iuse::teleport( player *p, item *it, bool, const tripoint & )
return 0;
}
p->moves -= to_moves<int>( 1_seconds );
g->teleport( p );
teleport::teleport(p);
return it->type->charges_to_use();
}

Expand Down Expand Up @@ -5275,7 +5276,7 @@ int iuse::artifact( player *p, item *it, bool, const tripoint & )
break;

case AEA_TELEPORT:
g->teleport( p );
teleport::teleport(p);
break;

case AEA_LIGHT:
Expand Down
1 change: 1 addition & 0 deletions src/magic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ std::string enum_to_string<spell_flag>( spell_flag data )
case spell_flag::SOMATIC: return "SOMATIC";
case spell_flag::NO_HANDS: return "NO_HANDS";
case spell_flag::NO_LEGS: return "NO_LEGS";
case spell_flag::UNSAFE_TELEPORT: return "UNSAFE_TELEPORT";
case spell_flag::CONCENTRATE: return "CONCENTRATE";
case spell_flag::RANDOM_AOE: return "RANDOM_AOE";
case spell_flag::RANDOM_DAMAGE: return "RANDOM_DAMAGE";
Expand Down
1 change: 1 addition & 0 deletions src/magic.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ enum spell_flag {
VERBAL, // spell makes noise at caster location, mouth encumbrance affects fail %
SOMATIC, // arm encumbrance affects fail % and casting time (slightly)
NO_HANDS, // hands do not affect spell energy cost
UNSAFE_TELEPORT, // teleport spell risks killing the caster or others
NO_LEGS, // legs do not affect casting time
CONCENTRATE, // focus affects spell fail %
RANDOM_AOE, // picks random number between min+increment*level and max instead of normal behavior
Expand Down
20 changes: 3 additions & 17 deletions src/magic_spell_effect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#include "rng.h"
#include "translations.h"
#include "timed_event.h"
#include "teleport.h"

static tripoint random_point( int min_distance, int max_distance, const tripoint &player_pos )
{
Expand All @@ -53,29 +54,14 @@ static tripoint random_point( int min_distance, int max_distance, const tripoint

void spell_effect::teleport_random( const spell &sp, Creature &caster, const tripoint & )
{
bool safe = !sp.has_flag(spell_flag::UNSAFE_TELEPORT);
const int min_distance = sp.range();
const int max_distance = sp.range() + sp.aoe();
if( min_distance > max_distance || min_distance < 0 || max_distance < 0 ) {
debugmsg( "ERROR: Teleport argument(s) invalid" );
return;
}
const tripoint player_pos = caster.pos();
tripoint target;
// limit the loop just in case it's impossble to find a valid point in the range
int tries = 0;
do {
target = random_point( min_distance, max_distance, player_pos );
tries++;
} while( g->m.impassable( target ) && tries < 20 );
if( tries == 20 ) {
add_msg( m_bad, _( "Unable to find a valid target for teleport." ) );
return;
}
// TODO: make this spell work for non players
if( caster.is_player() ) {
sp.make_sound( caster.pos() );
g->place_player( target );
}
teleport::teleport(&caster, min_distance, max_distance, safe, false);
}

void spell_effect::pain_split( const spell &sp, Creature &caster, const tripoint & )
Expand Down
4 changes: 2 additions & 2 deletions src/map_field.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
#include "point.h"
#include "scent_block.h"
#include "mongroup.h"
#include "teleport.h"

const species_id FUNGUS( "FUNGUS" );
const species_id INSECT( "INSECT" );
Expand Down Expand Up @@ -1632,10 +1633,9 @@ void map::player_in_field( player &u )
if( ft == fd_fatigue ) {
// Teleports you... somewhere.
if( rng( 0, 2 ) < cur.get_field_intensity() && u.is_player() ) {
// TODO: allow teleporting for npcs
add_msg( m_bad, _( "You're violently teleported!" ) );
u.hurtall( cur.get_field_intensity(), nullptr );
g->teleport();
teleport::teleport( &u );
}
}
// Why do these get removed???
Expand Down
3 changes: 2 additions & 1 deletion src/player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
#include "enums.h"
#include "flat_set.h"
#include "stomach.h"
#include "teleport.h"

const double MAX_RECOIL = 3000;

Expand Down Expand Up @@ -5575,7 +5576,7 @@ void player::suffer()
mutate();
}
if( has_artifact_with( AEP_FORCE_TELEPORT ) && one_turn_in( 1_hours ) ) {
g->teleport( this );
teleport::teleport( this );
}
const bool needs_fire = !has_morale( MORALE_PYROMANIA_NEARFIRE ) &&
!has_morale( MORALE_PYROMANIA_STARTFIRE );
Expand Down
3 changes: 2 additions & 1 deletion src/player_hardcoded_effects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "enums.h"
#include "mtype.h"
#include "stomach.h"
#include "teleport.h"

#if defined(TILES)
# if defined(_MSC_VER) && defined(USE_VCPKG)
Expand Down Expand Up @@ -616,7 +617,7 @@ void player::hardcoded_effects( effect &it )
if( !is_npc() ) {
add_msg( _( "Glowing lights surround you, and you teleport." ) );
}
g->teleport();
teleport::teleport( this );
g->events().send<event_type::teleglow_teleports>( getID() );
if( one_in( 10 ) ) {
// Set ourselves up for removal
Expand Down
93 changes: 93 additions & 0 deletions src/teleport.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#include "teleport.h"

#include "character.h"
#include "avatar.h"
#include "creature.h"
#include "player.h"
#include "monster.h"
#include "game.h"
#include "map.h"
#include "messages.h"
#include "point.h"


const efftype_id effect_teleglow("teleglow");

bool teleport::teleport( Creature * c, int min_distance, int max_distance, bool safe, bool add_teleglow)
{
if (c == nullptr || min_distance > max_distance) {
debugmsg("ERROR: Function teleport::teleport called with invalid arguments.");
return false;
}

bool c_is_u = (c == &g->u);
player *p = dynamic_cast<player *>(c);
int tries = 0;
tripoint origin = c->pos();
tripoint new_pos = tripoint_zero;
do {
int rangle = rng(0, 360);
int rdistance = rng(min_distance, max_distance);
new_pos.x =origin.x + rdistance * cos(rangle);
new_pos.y =origin.y + rdistance * sin(rangle);
tries++;
} while (g->m.impassable(new_pos) && tries < 20);
//handles teleporting into solids.
if (g->m.impassable(new_pos)) {
if (safe) {
if (c_is_u ) {
add_msg(m_bad, _("You cannot teleport safely"));
}
return false;
}
else {
c->apply_damage(nullptr, bp_torso, 9999);
if (c_is_u) {
g->events().send<event_type::teleports_into_wall>(p->getID(), g->m.obstacle_name(new_pos));
add_msg(m_bad, _("You die after teleporting within a solid"));
}
}
}
//handles telefragging other creatures
if (Creature *const poor_soul = g->critter_at<Creature>( new_pos ) ) {
if ( safe ){
if ( c_is_u ) {
add_msg(m_bad, _("You cannot teleport safely"));
}
return false;
}
else {
const bool poor_soul_is_u = (poor_soul == &g->u);
if (poor_soul_is_u) {
add_msg(m_bad, _("..."));
add_msg(m_bad, _("You exlpode into thousands of fragments."));
}
if (p) {
p->add_msg_player_or_npc(m_bad, _("You teleport into %s, and they explode into thousands of fragments."),
_("<npcname> teleports into %s, and they explode into thousands of fragments."), poor_soul->disp_name());
g->events().send<event_type::telefrags_creature>(p->getID(), poor_soul->get_name());
}
else {
if (g->u.sees(poor_soul->pos())) {
add_msg(m_good, _("%1$s teleports into %2$s, killing them!"),
c->disp_name(), poor_soul->disp_name());
}
}
poor_soul->apply_damage(nullptr, bp_torso, 9999); //Splatter real nice.
poor_soul->check_dead_state();
}
}

c->setpos(new_pos);
//player and npc exclusive teleporting effects
if (p) {
if (add_teleglow) {
add_msg(m_bad, _("unsafe"));
p->add_effect(effect_teleglow, 30_minutes);
}
}
if (c_is_u) {
g->update_map(*p);
}
return true;
}
15 changes: 15 additions & 0 deletions src/teleport.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#pragma once
#ifndef TELEPORT_H
#define TELEPORT_H

#include "creature.h"

namespace teleport
{
/** Teleports a creature to a tile within min_distance and max_distance tiles. Limited to 2D.
*bool safe determines wether the teleported creature can telefrag others/itself.
*/
bool teleport( Creature * c, int min_distance = 2, int max_distance = 12, bool safe = false, bool add_teleglow = true );
}

#endif
35 changes: 6 additions & 29 deletions src/trapfunc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "player.h"
#include "int_id.h"
#include "point.h"
#include "teleport.h"

const mtype_id mon_blob( "mon_blob" );
const mtype_id mon_shadow( "mon_shadow" );
Expand Down Expand Up @@ -638,39 +639,15 @@ bool trapfunc::telepad( const tripoint &p, Creature *c, item * )
if( c == nullptr ) {
return false;
}
monster *z = dynamic_cast<monster *>( c );
// TODO: NPC don't teleport?
if( c == &g->u ) {
c->add_msg_if_player( m_warning, _( "The air shimmers around you..." ) );
g->teleport();
return true;
} else if( z != nullptr ) {
if( g->u.sees( *z ) ) {
add_msg( _( "The air shimmers around the %s..." ), z->name() );
}

int tries = 0;
int newposx = 0;
int newposy = 0;
do {
newposx = rng( z->posx() - SEEX, z->posx() + SEEX );
newposy = rng( z->posy() - SEEY, z->posy() + SEEY );
tries++;
} while( g->m.impassable( point( newposx, newposy ) ) && tries != 10 );

if( tries == 10 ) {
z->die_in_explosion( nullptr );
} else if( monster *const mon_hit = g->critter_at<monster>( {newposx, newposy, z->posz()} ) ) {
if( g->u.sees( *z ) ) {
add_msg( m_good, _( "The %1$s teleports into a %2$s, killing them both!" ),
z->name(), mon_hit->name() );
}
mon_hit->die_in_explosion( z );
} else {
z->setpos( {newposx, newposy, z->posz()} );
}
else {
if (g->u.sees(p)) {
add_msg(_("The air shimmers around %s..."), c->disp_name());
}
return true;
}
teleport::teleport(c);
return false;
}

Expand Down

0 comments on commit 17d7ff2

Please sign in to comment.