Permalink
Browse files

Merge branch 'item-area-events', adding item ENTEREDAREA and LEFTAREA…

… events
  • Loading branch information...
frozenblit committed Nov 27, 2018
2 parents 8a1bf88 + 857553c commit dfb9bed403af43617fbd95a23abd2e86bf325cfc
@@ -2,9 +2,14 @@
<ESCRIPT>
<header>
<topic>Latest Core Changes</topic>
<datemodified>11-26-2018</datemodified>
<datemodified>11-27-2018</datemodified>
</header>
<version name="POL100">
<entry>
<date>11-27-2018</date>
<author>Nando:</author>
<change type="Added">Top-level items can now receive ENTEREDAREA and LEFTAREA events.</change>
</entry>
<entry>
<date>11-25-2018</date>
<author>Yukiko:</author>
@@ -62,7 +62,7 @@
<event>
<name>SYSEVENT_ENTEREDAREA</name>
<explain>A character entered inside a range around the NPC. Note, ignores Z distance.</explain>
<explain>A character entered inside a range around the NPC or top-level item. Note, ignores Z distance.</explain>
<ID>0x00000010</ID>
<member mname="type" value="SYSEVENT_ENTEREDAREA (0x00000010)"/>
<member mname="source" value="Character Reference"/>
@@ -73,7 +73,7 @@
<event>
<name>SYSEVENT_LEFTAREA</name>
<explain>A character left the range around the NPC. Note, ignores Z distance.</explain>
<explain>A character left the range around the NPC or top-level item. Note, ignores Z distance.</explain>
<ID>0x00000020</ID>
<member mname="type" value="SYSEVENT_LEFTAREA (0x00000020)"/>
<member mname="source" value="Character Reference"/>
@@ -1,9 +1,11 @@
-- POL100 --
11-27-2018 Nando:
Added: Top-level items can now receive ENTEREDAREA and LEFTAREA events.
11-25-2018 Yukiko:
Changed: The order of a couple of functions listed in uo.em. They were out of alphabetical order.
Added: To uo.em ListItemsInBoxOfObjType( objtype, x1, y1, z1, x2, y2, z2, realm := _DEFAULT_REALM)
Changed: The order of a couple of functions listed in uo.em. They were out of alphabetical order.
Added: To uo.em ListItemsInBoxOfObjType( objtype, x1, y1, z1, x2, y2, z2, realm := _DEFAULT_REALM)
The function returns an array of all items in the bounds of the coordinates matching the ObjType specified.
Added: To uo.em ListObjectsInBoxOfClass( POL_Class, x1, y1, z1, x2, y2, z2, realm := _DEFAULT_REALM)
Added: To uo.em ListObjectsInBoxOfClass( POL_Class, x1, y1, z1, x2, y2, z2, realm := _DEFAULT_REALM)
The function returns an array of all items in the bounds of the coordinates matching the POL_Class specified.
10-22-2018 Turley:
Fixed: Undefined behaviour after ~20 days due to overflow in time measurment. This fixes both internal time measurments e.g. for repeating tasks, swing,.. and for the EScript function ReadMilliSecondClock() see below.
@@ -28,6 +28,7 @@
#include "../gameclck.h"
#include "../globals/uvars.h"
#include "../mobile/charactr.h"
#include "../module/uomod.h"
#include "../network/client.h"
#include "../objtype.h"
#include "../polcfg.h"
@@ -1195,6 +1196,14 @@ double Item::getItemdescQuality() const
return itemdesc().quality;
}
Core::UOExecutor* Item::uoexec_control()
{
if ( process() != nullptr )
return &process()->uoexec;
return nullptr;
}
double Item::getQuality() const
{
return quality();
@@ -1212,5 +1221,76 @@ bool Item::get_method_hook( const char* methodname, Bscript::Executor* ex,
return true;
return base::get_method_hook( methodname, ex, hook, PC );
}
// Event notifications
bool Item::is_visible_to_me( const Mobile::Character* chr ) const
{
if ( chr == nullptr )
return false;
if ( chr->realm != this->realm )
return false; // noone can see across different realms.
if ( !chr->logged_in() )
return false;
// Unless the chr is offline or in a different realm,
// items can see anyone (I don't want to bother with privs now...)
return true;
}
void Pol::Items::Item::inform_leftarea( Mobile::Character* wholeft )
{
Core::UOExecutor* ex = uoexec_control();
if ( ex == nullptr || !ex->listens_to( Core::EVID_LEFTAREA ) )
return;
if ( pol_distance( wholeft, this ) > ex->area_size )
return;
if ( Core::settingsManager.ssopt.event_visibility_core_checks && !is_visible_to_me( wholeft ) )
return;
ex->signal_event( new Module::SourcedEvent( Core::EVID_LEFTAREA, wholeft ) );
}
void Pol::Items::Item::inform_enteredarea( Mobile::Character* whoentered )
{
Core::UOExecutor* ex = uoexec_control();
if ( ex == nullptr || !ex->listens_to( Core::EVID_ENTEREDAREA ) )
return;
if ( pol_distance( whoentered, this ) > ex->area_size )
return;
if ( Core::settingsManager.ssopt.event_visibility_core_checks && !is_visible_to_me( whoentered ) )
return;
ex->signal_event( new Module::SourcedEvent( Core::EVID_ENTEREDAREA, whoentered ) );
}
void Pol::Items::Item::inform_moved( Mobile::Character* moved )
{
Core::UOExecutor* ex = uoexec_control();
if ( ex == nullptr || !ex->listens_to( Core::EVID_ENTEREDAREA | Core::EVID_LEFTAREA ) )
return;
if ( Core::settingsManager.ssopt.event_visibility_core_checks && !is_visible_to_me( moved ) )
return;
const bool are_inrange =
( abs( x - moved->x ) <= ex->area_size ) && ( abs( y - moved->y ) <= ex->area_size );
const bool were_inrange =
( abs( x - moved->lastx ) <= ex->area_size ) && ( abs( y - moved->lasty ) <= ex->area_size );
if ( are_inrange && !were_inrange && ex->listens_to( Core::EVID_ENTEREDAREA ) )
{
ex->signal_event( new Module::SourcedEvent( Core::EVID_ENTEREDAREA, moved ) );
}
else if ( !are_inrange && were_inrange && ex->listens_to( Core::EVID_LEFTAREA ) )
{
ex->signal_event( new Module::SourcedEvent( Core::EVID_LEFTAREA, moved ) );
}
}
} // namespace Items
} // namespace Pol
@@ -49,10 +49,11 @@ class UOExecutorModule;
namespace Core
{
class UContainer;
class UOExecutor;
std::string format_description( unsigned int polflags, const std::string& descdef,
unsigned short amount, const std::string suffix );
}
} // namespace Core
namespace Mobile
{
class Character;
@@ -61,7 +62,7 @@ namespace Multi
{
class UHouse;
class UMulti;
}
} // namespace Multi
namespace Network
{
class Client;
@@ -88,6 +89,11 @@ class Item : public Core::UObject
virtual void builtin_on_use( Network::Client* client );
virtual void walk_on( Mobile::Character* chr );
bool is_visible_to_me( const Mobile::Character* chr ) const;
virtual void inform_leftarea( Mobile::Character* wholeft );
virtual void inform_enteredarea( Mobile::Character* whoentered );
virtual void inform_moved( Mobile::Character* moved );
const ItemDesc& itemdesc() const;
virtual u16 get_senditem_amount() const;
@@ -257,6 +263,8 @@ class Item : public Core::UObject
Core::UContainer* container;
protected:
Core::UOExecutor* uoexec_control();
unsigned int decayat_gameclock_;
u16 amount_;
u8 slot_index_;
@@ -390,6 +398,6 @@ inline bool valid_equip_layer( const Item* item )
{
return valid_equip_layer( item->tile_layer );
}
}
}
} // namespace Items
} // namespace Pol
#endif
@@ -130,18 +130,27 @@ const std::string Realm::name() const
void Realm::notify_moved( Mobile::Character& whomoved )
{
// When the movement is larger than 32 tiles, notify mobiles in the old location
// When the movement is larger than 32 tiles, notify mobiles and items in the old location
if ( Core::pol_distance( whomoved.lastx, whomoved.lasty, whomoved.x, whomoved.y ) > 32 )
{
Core::WorldIterator<Core::MobileFilter>::InRange(
whomoved.lastx, whomoved.lasty, this, 32,
[&]( Mobile::Character* chr ) { Mobile::NpcPropagateMove( chr, &whomoved ); } );
Core::WorldIterator<Core::ItemFilter>::InRange(
whomoved.lastx, whomoved.lasty, this, 32,
[&]( Items::Item* item ) { item->inform_moved( &whomoved ); } );
}
// Inform nearby mobiles that a movement has been made.
Core::WorldIterator<Core::MobileFilter>::InRange(
whomoved.x, whomoved.y, this, 33,
[&]( Mobile::Character* chr ) { Mobile::NpcPropagateMove( chr, &whomoved ); } );
// the same for top-level items
Core::WorldIterator<Core::ItemFilter>::InRange(
whomoved.x, whomoved.y, this, 33,
[&]( Items::Item* item ) { item->inform_moved( &whomoved ); } );
}
// The unhid character was already in the area and must have seen the other mobiles. So only notify
@@ -151,6 +160,10 @@ void Realm::notify_unhid( Mobile::Character& whounhid )
Core::WorldIterator<Core::NPCFilter>::InRange(
whounhid.x, whounhid.y, this, 32,
[&]( Mobile::Character* chr ) { Mobile::NpcPropagateEnteredArea( chr, &whounhid ); } );
Core::WorldIterator<Core::ItemFilter>::InRange(
whounhid.x, whounhid.y, this, 32,
[&]( Items::Item* item ) { item->inform_enteredarea( &whounhid ); } );
}
// Resurrecting is just like unhiding
@@ -168,6 +181,11 @@ void Realm::notify_entered( Mobile::Character& whoentered )
chr ); // Notify the one who entered this area about
// the mobiles that were already there
} );
// and notify the top-level items too
Core::WorldIterator<Core::ItemFilter>::InRange(
whoentered.x, whoentered.y, this, 32,
[&]( Items::Item* item ) { item->inform_enteredarea( &whoentered ); } );
}
// Must be used right before a mobile leaves (before updating x and y)
@@ -176,6 +194,10 @@ void Realm::notify_left( Mobile::Character& wholeft )
Core::WorldIterator<Core::MobileFilter>::InRange(
wholeft.x, wholeft.y, this, 32,
[&]( Mobile::Character* chr ) { Mobile::NpcPropagateLeftArea( chr, &wholeft ); } );
Core::WorldIterator<Core::ItemFilter>::InRange(
wholeft.x, wholeft.y, this, 32,
[&]( Items::Item* item ) { item->inform_leftarea( &wholeft ); } );
}
// This function will be called whenever:

0 comments on commit dfb9bed

Please sign in to comment.