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

Dragging vehicles #2520

Merged
merged 13 commits into from
Aug 22, 2013
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions action.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,8 @@ std::string action_ident(action_id act)
return "advinv";
case ACTION_PICKUP:
return "pickup";
case ACTION_GRAB:
return "grab";
case ACTION_BUTCHER:
return "butcher";
case ACTION_CHAT:
Expand Down Expand Up @@ -355,6 +357,8 @@ std::string action_name(action_id act)
return _("Examine Nearby Terrain");
case ACTION_PICKUP:
return _("Pick Item(s) Up");
case ACTION_GRAB:
return _("Grab a nearby vehicle");
case ACTION_BUTCHER:
return _("Butcher");
case ACTION_CHAT:
Expand Down
1 change: 1 addition & 0 deletions action.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ ACTION_CLOSE,
ACTION_SMASH,
ACTION_EXAMINE,
ACTION_PICKUP,
ACTION_GRAB,
ACTION_BUTCHER,
ACTION_CHAT,
ACTION_LOOK,
Expand Down
115 changes: 111 additions & 4 deletions game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1871,6 +1871,10 @@ bool game::handle_action()
pickup(u.posx, u.posy, 1);
break;

case ACTION_GRAB:
grab();
break;

case ACTION_BUTCHER:
butcher();
break;
Expand Down Expand Up @@ -8849,6 +8853,32 @@ void game::pickup(int posx, int posy, int min)
delwin(w_item_info);
}

// Establish or release a grab on a vehicle
void game::grab()
{
int grabx = 0;
int graby = 0;
if( 0 != u.grab_point.x || 0 != u.grab_point.y ) {
vehicle *veh = m.veh_at( u.posx + u.grab_point.x, u.posy + u.grab_point.y );
if( veh ) { add_msg(_("You release %s."), veh->name.c_str() ); }
u.grab_point.x = 0;
u.grab_point.y = 0;
return;
}
if( choose_adjacent( _("Grab"), grabx, graby ) ) {
vehicle *veh = m.veh_at(grabx, graby);
if( veh != NULL ) {
u.grab_point.x = grabx - u.posx;
u.grab_point.y = graby - u.posy;
add_msg(_("You grab the %s."), veh->name.c_str());
} else {
add_msg(_("There's no vehicle to grab there!"));
}
} else {
add_msg(_("Never Mind."));
}
}

// Handle_liquid returns false if we didn't handle all the liquid.
bool game::handle_liquid(item &liquid, bool from_ground, bool infinite, item *source)
{
Expand Down Expand Up @@ -10165,7 +10195,7 @@ void game::pldrive(int x, int y) {
u.practice(turn, "driving", 1);
}

void game::plmove(int x, int y)
void game::plmove(int dx, int dy)
{
if (run_mode == 2) { // Monsters around and we don't wanna run
add_msg(_("Monster spotted--safe mode is on! \
Expand All @@ -10174,12 +10204,14 @@ void game::plmove(int x, int y)
from_sentence_case(press_x(ACTION_IGNORE_ENEMY)).c_str());
return;
}
int x = 0;
int y = 0;
if (u.has_disease("stunned")) {
x = rng(u.posx - 1, u.posx + 1);
y = rng(u.posy - 1, u.posy + 1);
} else {
x += u.posx;
y += u.posy;
x = u.posx + dx;
y = u.posy + dy;

if (moveCount % 60 == 0) {
if (u.has_bionic("bio_torsionratchet")) {
Expand Down Expand Up @@ -10281,6 +10313,16 @@ void game::plmove(int x, int y)
int vpart0 = -1, vpart1 = -1, dpart = -1;
vehicle *veh0 = m.veh_at(u.posx, u.posy, vpart0);
vehicle *veh1 = m.veh_at(x, y, vpart1);
if( u.grab_point.x != 0 || u.grab_point.y ) {
vehicle *grabbed_vehicle = m.veh_at( u.posx + u.grab_point.x, u.posy + u.grab_point.y );
// If we're pushing a vehicle, the vehicle tile we'd be "stepping onto" is
// actually the current tile.
// If there's a vehicle there, it will actually result in failed movement.
if( grabbed_vehicle == veh1 ) {
veh1 = veh0;
vpart1 = vpart0;
}
}
bool veh_closed_door = false;
if (veh1) {
dpart = veh1->part_with_feature (vpart1, vpf_openable);
Expand Down Expand Up @@ -10336,9 +10378,63 @@ void game::plmove(int x, int y)
return;
}

float drag_multiplier = 1.0;
vehicle *grabbed_vehicle = NULL;
if( u.grab_point.x != 0 || u.grab_point.y != 0 ) {
grabbed_vehicle = m.veh_at( u.posx + u.grab_point.x, u.posy + u.grab_point.y );
if( NULL != grabbed_vehicle ) {
if( grabbed_vehicle == veh0 ) {
add_msg(_("You can't move %s while standing on it!"), grabbed_vehicle->name.c_str());
return;
}
drag_multiplier += (float)(grabbed_vehicle->total_mass() * 1000) /
(float)(u.weight_capacity() * 5);
if( drag_multiplier > 2.0 ) {
add_msg(_("The %s is too heavy for you to budge!"), grabbed_vehicle->name.c_str());
return;
}
tileray mdir;
mdir.init( dx, dy );
mdir.advance( 1 );
grabbed_vehicle->precalc_mounts( 1, mdir.dir() );
int imp = 0;
std::vector<veh_collision> veh_veh_colls;
bool can_move = true;
// Set player location to illegal value so it can't collide with vehicle.
int player_prev_x = u.posx;
int player_prev_y = u.posy;
u.posx = 0;
u.posy = 0;
if( grabbed_vehicle->collision( veh_veh_colls, dx, dy, can_move, imp, true ) ) {
// TODO: figure out what we collided with.
add_msg( _("The %s collides with something."), grabbed_vehicle->name.c_str() );
u.moves -= 10;
u.posx = player_prev_x;
u.posy = player_prev_y;
return;
}
u.posx = player_prev_x;
u.posy = player_prev_y;
int gx = grabbed_vehicle->global_x();
int gy = grabbed_vehicle->global_y();
for( int ep = 0; ep < grabbed_vehicle->external_parts.size(); ep++ ) {
const int p = grabbed_vehicle->external_parts[ ep ];
if( grabbed_vehicle->part_flag( p, vpf_wheel ) && one_in(2) )
grabbed_vehicle->handle_trap( gx + grabbed_vehicle->parts[p].precalc_dx[0] + dx,
gy + grabbed_vehicle->parts[p].precalc_dy[0] + dy, p );
}
m.displace_vehicle( this, gx, gy, dx, dy );
} else {
add_msg( _("No vehicle at grabbed point.") );
u.grab_point.x = 0;
u.grab_point.y = 0;
}
}

// Calculate cost of moving
bool diag = trigdist && u.posx != x && u.posy != y;
u.moves -= u.run_cost(m.combined_movecost(u.posx, u.posy, x, y), diag);
u.moves -= u.run_cost(m.combined_movecost(u.posx, u.posy, x, y, grabbed_vehicle), diag) *
drag_multiplier;

// Adjust recoil down
if (u.recoil > 0) {
Expand Down Expand Up @@ -10407,6 +10503,7 @@ void game::plmove(int x, int y)
z[mondex].move_to(this, u.posx, u.posy, true); // Force the movement even though the player is there right now.
add_msg(_("You displace the %s."), z[mondex].name().c_str());
}

if (x < SEEX * int(MAPSIZE / 2) || y < SEEY * int(MAPSIZE / 2) ||
x >= SEEX * (1 + int(MAPSIZE / 2)) || y >= SEEY * (1 + int(MAPSIZE / 2)))
update_map(x, y);
Expand Down Expand Up @@ -10804,6 +10901,16 @@ void game::vertical_move(int movez, bool force)
return;
}

if( force ) {
// Let go of a grabbed cart.
u.grab_point.x = 0;
u.grab_point.y = 0;
} else {
// TODO: Warp the cart along with you if you're on an elevator
add_msg(_("You can't drag things up and down stairs."));
return;
}

map tmpmap(&traps);
tmpmap.load(this, levx, levy, levz + movez, false);
// Find the corresponding staircase
Expand Down
2 changes: 2 additions & 0 deletions game.h
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,8 @@ void load_artifacts(); // Load artifact data
// open vehicle interaction screen
void exam_vehicle(vehicle &veh, int examx, int examy, int cx=0, int cy=0);
void pickup(int posx, int posy, int min);// Pickup items; ',' or via examine()
// Establish a grab on something.
void grab();
// Pick where to put liquid; false if it's left where it was

void compare(int iCompareX = -999, int iCompareY = -999); // Compare two Items 'I'
Expand Down
4 changes: 4 additions & 0 deletions itypedef.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ VAR_VEH_PART("wheel_small", _("small wheel"),140, ']', c_dkgray, "steel", "p
9, 2722, 10, 0, -1, 0, 6, 14, BIGNESS_WHEEL_DIAMETER, _("\
A pretty small wheel. Probably from one of those segway things.\
It is not very menacing."));
VAR_VEH_PART("wheel_caster", _("casters"),140, ']', c_dkgray, "steel", "plastic",
// VOL WGT DAM CUT HIT FLAGS BIGNESS_MIN BIGNESS_MAX ASPECT
5, 1500, 6, 0, -1, 0, 4, 6, BIGNESS_WHEEL_DIAMETER, _("\
A set of casters, like on a shopping cart."));

// NAME RAR PRC SYM COLOR MAT1 MAT2
VAR_VEH_PART("1cyl_combustion", _("1-cylinder engine"), 100, ':', c_ltcyan, "iron", "null",
Expand Down
5 changes: 3 additions & 2 deletions keypress.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ move_down >\n\
move_up <\n\
\n\
# MOVEMENT:\n\
center G\n\
center :\n\
shift_n K\n\
shift_e L\n\
shift_s J\n\
Expand All @@ -193,6 +193,7 @@ smash s\n\
examine e\n\
advinv /\n\
pickup , g\n\
grab G\n\
butcher B\n\
chat C\n\
look ; x\n\
Expand Down Expand Up @@ -238,7 +239,7 @@ quit Q\n\
\n\
# INFO SCREENS\n\
player_data @\n\
map m :\n\
map m\n\
missions M\n\
factions #\n\
kills )\n\
Expand Down
30 changes: 8 additions & 22 deletions map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ void map::destroy_vehicle (vehicle *veh)
debugmsg ("destroy_vehicle can't find it! sm=%d", veh_sm);
}

bool map::displace_vehicle (game *g, int &x, int &y, const int dx, const int dy, bool test=false)
bool map::displace_vehicle (game *g, int &x, int &y, const int dx, const int dy, bool test)
{
const int x2 = x + dx;
const int y2 = y + dy;
Expand Down Expand Up @@ -554,22 +554,7 @@ bool map::vehproceed(game* g){
if (veh->velocity == 0)
can_move = false;
// find collisions
for (int ep = 0; ep < veh->external_parts.size() && can_move; ep++) {
const int p = veh->external_parts[ep];
// coords of where part will go due to movement (dx/dy)
// and turning (precalc_dx/dy [1])
const int dsx = x + dx + veh->parts[p].precalc_dx[1];
const int dsy = y + dy + veh->parts[p].precalc_dy[1];
veh_collision coll = veh->part_collision (x, y, p, dsx, dsy);
if(coll.type == veh_coll_veh)
veh_veh_colls.push_back(coll);
else if (coll.type != veh_coll_nothing){ //run over someone?
if (can_move)
imp += coll.imp;
if (veh->velocity == 0)
can_move = false;
}
}
veh->collision( veh_veh_colls, dx, dy, can_move, imp );

if(veh_veh_colls.size()){ // we have dynamic crap!
// effects of colliding with another vehicle:
Expand Down Expand Up @@ -870,11 +855,11 @@ std::string map::features(const int x, const int y)
return ret;
}

int map::move_cost(const int x, const int y)
int map::move_cost(const int x, const int y, const vehicle *ignored_vehicle)
{
int vpart = -1;
vehicle *veh = veh_at(x, y, vpart);
if (veh) { // moving past vehicle cost
if (veh && veh != ignored_vehicle) { // moving past vehicle cost
const int dpart = veh->part_with_feature(vpart, vpf_obstacle);
if (dpart >= 0 && (!veh->part_flag(dpart, vpf_openable) || !veh->parts[dpart].open)) {
return 0;
Expand All @@ -897,10 +882,11 @@ int map::move_cost_ter_furn(const int x, const int y)
}

int map::combined_movecost(const int x1, const int y1,
const int x2, const int y2)
const int x2, const int y2,
const vehicle *ignored_vehicle)
{
int cost1 = move_cost(x1, y1);
int cost2 = move_cost(x2, y2);
int cost1 = move_cost(x1, y1, ignored_vehicle);
int cost2 = move_cost(x2, y2, ignored_vehicle);
// 50 moves taken per move_cost (70.71.. diagonally)
int mult = (trigdist && x1 != x2 && y1 != y2 ? 71 : 50);
return (cost1 + cost2) * mult / 2;
Expand Down
7 changes: 4 additions & 3 deletions map.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ class map
* 0 | Impassable
* n > 0 | x*n turns to move past this
*/
int move_cost(const int x, const int y);
int move_cost(const int x, const int y, const vehicle *ignored_vehicle = NULL);


/**
Expand All @@ -189,7 +189,8 @@ class map
*
* @return The cost in turns to move out of `(x1, y1)` and into `(x2, y2)`
*/
int combined_movecost(const int x1, const int y1, const int x2, const int y2);
int combined_movecost(const int x1, const int y1, const int x2, const int y2,
const vehicle *ignored_vehicle = NULL);

/**
* Returns whether the tile at `(x, y)` is transparent(you can look past it).
Expand Down Expand Up @@ -259,7 +260,7 @@ class map
// Returns true, if there was a submap change.
// If test is true, function only checks for submap change, no displacement
// WARNING: not checking collisions!
bool displace_vehicle (game *g, int &x, int &y, const int dx, const int dy, bool test);
bool displace_vehicle (game *g, int &x, int &y, const int dx, const int dy, bool test = false);
void vehmove(game* g); // Vehicle movement
bool vehproceed(game* g);
// move water under wheels. true if moved
Expand Down