polserver/pol-core/pol/module/uomod4.cpp
turleypol 6a2bd7c705 Merge remote-tracking branch 'origin/master' into vector_classes
* origin/master: (93 commits)
  Add support for dictionary creation (#277)
  Add do-while statement (#276)
  Add foreach loops (#275)
  New compiler: array initialization (#274)
  Disambiguator: figure out if label is a case statement dispatch selector, or should apply to a statement within the case dispatch group's block. (#273)
  New compiler: Add support for case statements (#272)
  Change "logical" to "bitwise". (#258)
  Fix divide-by-zero errors, and mask FormatError if it were thrown in a destructor. (#271)
  Add break and continue statements. (#270)
  New compiler: assignment to local and global variables. (#269)
  Add support for while loops (#268)
  Optimize if statements, and emit module functions in legacy order (#267)
  Optimizations: binary operators (#266)
  Add binary operators (#265)
  Add support for const declarations (#264)
  Handle default parameter values, pass-by-name, and return statements in functions. (#263)
  Add limited support for user functions (#262)
  New compiler: add return and exit statements (#261)
  Add support for if-then-else statements (#259)
  OG compiler: set module to Mod_Basic when a token is an identifier (#257)
  ...
2020-09-06 20:14:26 +02:00

189 lines
5.7 KiB
C++

/** @file
*
* @par History
* - 2005/12/06 Shinigami: fixed <un-/signed>(z)-bug inside internal_MoveCharacter() to fix z<0
* problem
*/
/*
UEMOD4.CPP
Handles moving objects within a realm and from realm to realm.
*/
#include <stddef.h>
#include <string>
#include "../../bscript/berror.h"
#include "../../bscript/bobject.h"
#include "../../bscript/impstr.h"
#include "../../plib/uconst.h"
#include "../containr.h"
#include "../core.h"
#include "../item/item.h"
#include "../mobile/charactr.h"
#include "../multi/boat.h"
#include "../polclass.h"
#include "realms/realms.h"
#include "realms/realm.h"
#include "../ufunc.h"
#include "../uobject.h"
#include "../uworld.h"
#include "uomod.h"
namespace Pol
{
namespace Module
{
using namespace Bscript;
using namespace Mobile;
using namespace Core;
using namespace Items;
BObjectImp* UOExecutorModule::mf_MoveObjectToLocation( /*object, x, y, z, realm, flags*/ )
{
UObject* obj;
Core::Pos4d pos;
int flags;
if ( !( getUObjectParam( 0, obj ) && getPos4dParam( 1, 2, 3, 4, &pos ) && getParam( 5, flags ) ) )
{
return new BError( "Invalid parameter" );
}
if ( obj->script_isa( POLCLASS_MOBILE ) )
return internal_MoveCharacter( static_cast<Character*>( obj ), pos, flags );
else if ( obj->script_isa( POLCLASS_BOAT ) )
return internal_MoveBoat( static_cast<Multi::UBoat*>( obj ), pos, flags );
else if ( obj->script_isa( POLCLASS_MULTI ) )
return new BError( "Can't move multis at this time." );
else if ( obj->script_isa( POLCLASS_ITEM ) )
return internal_MoveItem( static_cast<Item*>( obj ), pos, flags );
else
return new BError( "Can't handle that object type." );
}
BObjectImp* UOExecutorModule::internal_MoveCharacter( Character* chr, Core::Pos4d newpos,
int flags )
{
s8 newz;
if ( !( flags & MOVEITEM_FORCELOCATION ) )
{
if ( newpos.realm() != nullptr )
{
if ( !newpos.realm()->walkheight( newpos.xy(), newpos.z(), &newz, nullptr, nullptr, true,
chr->movemode ) )
return new BError( "Can't go there" );
}
}
if ( newpos.realm() == nullptr )
newpos = Core::Pos4d( newpos.xyz(), chr->realm() );
bool ok = move_character_to( chr, newpos, flags );
if ( ok )
return new BLong( 1 );
else
return new BError( "Can't go there" );
}
BObjectImp* UOExecutorModule::internal_MoveBoat( Multi::UBoat* boat, Core::Pos4d newpos, int flags )
{
{ // local scope for reg/unreg guard
Multi::UBoat::BoatMoveGuard registerguard( boat );
if ( !boat->navigable( boat->multidef(), newpos ) )
{
return new BError( "Position indicated is impassable" );
}
}
return new BLong( boat->move_to( newpos, flags ) );
}
BObjectImp* UOExecutorModule::internal_MoveItem( Item* item, Core::Pos4d newpos, int flags )
{
ItemRef itemref( item ); // dave 1/28/3 prevent item from being destroyed before function ends
Core::Pos4d oldpos( item->toplevel_pos() );
if ( oldpos.realm() == nullptr ) // see below setposition
oldpos = Core::Pos4d( oldpos.xyz(), newpos.realm() );
if ( !( flags & MOVEITEM_IGNOREMOVABLE ) && !item->movable() )
{
Character* chr = controller_.get();
if ( chr == nullptr || !chr->can_move( item ) )
return new BError( "That is immobile" );
}
if ( item->inuse() && !is_reserved_to_me( item ) )
{
return new BError( "That item is being used." );
}
Multi::UMulti* multi = nullptr;
if ( flags & MOVEITEM_FORCELOCATION )
{
s8 newz;
newpos.realm()->walkheight( newpos.xy(), newpos.z(), &newz, &multi, nullptr, true,
Plib::MOVEMODE_LAND );
// note that newz is ignored...
}
else
{
s8 newz;
if ( !newpos.realm()->walkheight( newpos.xy(), newpos.z(), &newz, &multi, nullptr, true,
Plib::MOVEMODE_LAND ) )
{
return new BError( "Invalid location selected" );
}
newpos.z( newz );
}
if ( item->container != nullptr )
{
// DAVE added this 12/04, call can/onRemove scripts for the old container
UContainer* oldcont = item->container;
Character* chr_owner = oldcont->toplevel_chr();
if ( chr_owner == nullptr )
if ( controller_.get() != nullptr )
chr_owner = controller_.get();
// dave changed 1/26/3 order of scripts to call. added unequip/test script call
if ( !oldcont->check_can_remove_script( chr_owner, item, UContainer::MT_CORE_MOVED ) )
{
return new BError( "Could not remove item from its container." );
}
else if ( item->orphan() ) // dave added 1/28/3, item might be destroyed in RTC script
{
return new BError( "Item was destroyed in CanRemove script" );
}
if ( !item->check_unequiptest_scripts() || !item->check_unequip_script() )
{
return new BError( "Item cannot be unequipped" );
}
if ( item->orphan() ) // dave added 1/28/3, item might be destroyed in RTC script
return new BError( "Item was destroyed in Equip script" );
oldcont->on_remove( chr_owner, item, UContainer::MT_CORE_MOVED );
if ( item->orphan() ) // dave added 1/28/3, item might be destroyed in RTC script
{
return new BError( "Item was destroyed in OnRemove script" );
}
item->set_dirty();
item->extricate();
// wherever it was, it wasn't in the world/on the ground
item->setposition( oldpos );
// move_item calls MoveItemWorldLocation, so this gets it
// in the right place to start with.
add_item_to_world( item ); // TODO: we have to add it first....
}
item->setposition( newpos );
move_item( item, newpos, oldpos );
if ( multi != nullptr )
{
multi->register_object( item );
}
return new BLong( 1 );
}
} // namespace Module
} // namespace Pol