mirror of
https://github.com/polserver/polserver
synced 2026-08-13 08:23:08 -04:00
* 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) ...
189 lines
5.7 KiB
C++
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
|