Pol  Revision:cb584c9
target.cpp
Go to the documentation of this file.
1 
10 #include "target.h"
11 
12 #include <stddef.h>
13 
14 #include "../clib/clib_endian.h"
15 #include "../clib/logfacility.h"
16 #include "../clib/rawtypes.h"
17 #include "accounts/account.h"
18 #include "fnsearch.h"
19 #include "globals/uvars.h"
20 #include "guardrgn.h"
21 #include "item/itemdesc.h"
22 #include "mobile/charactr.h"
23 #include "multi/multi.h"
24 #include "network/client.h"
25 #include "network/packethelper.h"
26 #include "network/packets.h"
27 #include "pktboth.h"
28 #include "polclass.h"
29 #include "realms/realm.h"
30 #include "ufunc.h"
31 #include "uobject.h"
32 
33 namespace Pol
34 {
35 namespace Core
36 {
38 {
39  Mobile::Character* targetter = client->chr;
40  u32 target_cursor_serial = cfBEu32( msg->target_cursor_serial );
41 
42  // does target cursor even exist? (NOTE 1-based)
43  if ( target_cursor_serial == 0 ||
44  target_cursor_serial > gamestate.target_cursors._cursorid_count )
45  {
46  return;
47  }
48 
49  TargetCursor* tcursor = gamestate.target_cursors._target_cursors[target_cursor_serial - 1];
50  if ( tcursor != targetter->tcursor2 )
51  {
52  POLLOG_ERROR << targetter->acct->name() << "/" << targetter->name()
53  << " used out of sequence cursor.\n";
54 
55  targetter->tcursor2 = nullptr;
56  return;
57  }
58 
59  targetter->tcursor2 = nullptr;
60  tcursor->handle_target_cursor( targetter, msg );
61 }
62 
63 /*
64 Target Cursor messages come in different forms:
65 1) Item selected:
66 'create': 0
67 target_cursor_serial: serial of cursor
68 unk6: 0
69 selected_serial: serial of selected item
70 x: x-pos of selected item
71 y: y-pos of selected item
72 unk15: 0
73 z: z-pos of selected item
74 objtype: objtype of selected item
75 2) Character selected:
76 same as for (1)
77 3) Cursor Cancelled:
78 create is 0
79 target_cursor_serial: serial of cursor
80 unk6: 0
81 selected_serial: 0
82 x: 0xffff
83 y: 0xffff
84 unk15: 0
85 z: 0
86 objtype: 0
87 4) Static targetted:
88 create is 1
89 target_cursor_serial: serial of cursor
90 unk6: 0
91 selected_serial: 0
92 x: x-pos
93 y: y-pos
94 unk15: 0
95 z: z-pos
96 objtype: objtype of item
97 5) Backpack on a paperdoll selected
98 create is 0
99 target_cursor_serial: serial of cursor
100 cursor_type: 0
101 selected_serial: serial of backpack
102 x: 0xffff
103 y: 0xffff
104 unk15: 0
105 z: 0
106 objtype: objtype of backpack
107 */
108 
109 /*
110 struct {
111 void (*func)(Client *client, PKTBI_6C *msg);
112 } target_handlers[ MAX_CURSORS ];
113 */
114 
115 TargetCursor::TargetCursor( bool inform_on_cancel ) : inform_on_cancel_( inform_on_cancel )
116 {
118  {
119  throw std::runtime_error( "Too many targetting cursors!" );
120  }
121 
123 
125 
127 }
128 
129 // FIXME we need something like is done for item menus, where we check
130 // to make sure that he client has any business using this menu - in this
131 // case, we need to make sure the client is supposed to have an active cursor.
132 
134 {
135  if ( !client->chr->target_cursor_busy() )
136  {
138  msg->Write<u8>( PKTBI_6C::UNK1_00 );
139  msg->WriteFlipped<u32>( cursorid_ );
140  msg->Write<u8>( crstype );
141  // rest 0
142  msg.Send( client, sizeof msg->buffer );
143  client->chr->tcursor2 = this;
144  return true;
145  }
146  else
147  {
148  return false;
149  }
150 }
151 
153 {
154  chr->tcursor2 = nullptr;
155  if ( inform_on_cancel_ )
156  on_target_cursor( chr, nullptr );
157 }
158 
160 {
161  if ( msg->selected_serial != 0 ) // targetted something
162  {
163  if ( chr->dead() ) // but is dead
164  {
165  if ( chr->client != nullptr )
166  send_sysmessage( chr->client, "I am dead and cannot do that." );
167  cancel( chr );
168  return;
169  }
170 
171  if ( ( chr->frozen() || chr->paralyzed() ) && !chr->can_freemove() )
172  {
173  if ( chr->client != nullptr )
174  {
175  if ( chr->frozen() )
176  private_say_above( chr, chr, "I am frozen and cannot do that." );
177  else if ( chr->paralyzed() )
178  private_say_above( chr, chr, "I am paralyzed and cannot do that." );
179  }
180  cancel( chr );
181  return;
182  }
183 
184  u32 selected_serial = cfBEu32( msg->selected_serial );
185  UObject* obj = system_find_object( selected_serial );
186  if ( obj != nullptr && obj->script_isa( POLCLASS_MOBILE ) && !obj->script_isa( POLCLASS_NPC ) )
187  {
188  Mobile::Character* targeted = find_character( selected_serial );
189  // check for when char is not logged on
190  if ( targeted != nullptr )
191  {
192  if ( !chr->is_visible_to_me( targeted ) )
193  {
194  cancel( chr );
195  return;
196  }
197 
198  if ( msg->cursor_type == 1 )
199  {
200  if ( ( JusticeRegion::RunNoCombatCheck( chr->client ) == true ) ||
201  ( JusticeRegion::RunNoCombatCheck( targeted->client ) == true ) )
202  {
203  send_sysmessage( chr->client, "Combat is not allowed in this area." );
204  cancel( chr );
205  return;
206  }
207  }
208  }
209  }
210  }
211 
212  if ( msg->x != 0xffff || msg->selected_serial != 0 )
213  on_target_cursor( chr, msg );
214  else
215  cancel( chr );
216 }
217 
219  : TargetCursor( false /* don't inform on cancel */ ), func( func )
220 {
221 }
222 
224 {
225  ( *func )( chr, msg );
226 }
227 
228 
229 /******************************************************/
231  bool inform_on_cancel )
232  : TargetCursor( inform_on_cancel ), func( func )
233 {
234 }
235 
237 {
238  if ( msgin == nullptr )
239  {
240  ( *func )( chr, nullptr );
241  return;
242  }
243 
244  u32 selected_serial = cfBEu32( msgin->selected_serial );
245 
246  UObject* uobj = find_toplevel_object( selected_serial );
247  // FIXME inefficient, but neither works well by itself.
248  bool additlegal = false;
249  if ( uobj == nullptr )
250  uobj = find_legal_item( chr, selected_serial, &additlegal );
251 
252  if ( uobj == nullptr )
253  uobj = system_find_multi( selected_serial );
254 
255  if ( uobj == nullptr )
256  {
257  if ( chr->client != nullptr )
258  send_sysmessage( chr->client, "What you selected does not seem to exist." );
259  if ( inform_on_cancel_ )
260  ( *func )( chr, nullptr );
261  return;
262  }
263 
264  if ( !additlegal && !chr->realm->has_los( *chr, *uobj->toplevel_owner() ) )
265  {
266  if ( chr->client != nullptr )
267  send_sysmessage( chr->client, "That is not within your line of sight." );
268  if ( inform_on_cancel_ )
269  ( *func )( chr, nullptr );
270  return;
271  }
272 
273  ( *func )( chr, uobj );
274 }
275 /******************************************************/
276 
277 
278 /******************************************************/
280  bool inform_on_cancel )
281  : TargetCursor( inform_on_cancel ), func( func )
282 {
283 }
284 
286 {
287  if ( msgin == nullptr )
288  {
289  ( *func )( chr, nullptr );
290  return;
291  }
292 
293  u32 selected_serial = cfBEu32( msgin->selected_serial );
294 
295  UObject* uobj = find_toplevel_object( selected_serial );
296  // FIXME inefficient, but neither works well by itself.
297  bool additlegal = false;
298  if ( uobj == nullptr )
299  uobj = find_legal_item( chr, selected_serial, &additlegal );
300 
301  if ( uobj == nullptr )
302  uobj = system_find_multi( selected_serial );
303 
304  if ( uobj == nullptr )
305  {
306  if ( chr->client != nullptr )
307  send_sysmessage( chr->client, "What you selected does not seem to exist." );
308  if ( inform_on_cancel_ )
309  ( *func )( chr, nullptr );
310  return;
311  }
312 
313  ( *func )( chr, uobj );
314 }
315 /******************************************************/
316 
317 
319  bool inform_on_cancel )
320  : TargetCursor( inform_on_cancel ), func_( func )
321 {
322 }
323 
325 {
326  if ( !client->chr->target_cursor_busy() )
327  {
329  msg->Write<u8>( PKTBI_6C::UNK1_01 );
330  msg->WriteFlipped<u32>( cursorid_ );
331  msg->Write<u8>( PKTBI_6C::CURSOR_TYPE_NEUTRAL );
332  // rest 0
333  msg.Send( client, sizeof msg->buffer );
334  client->chr->tcursor2 = this;
335  return true;
336  }
337  else
338  {
339  return false;
340  }
341 }
342 
344 {
345  ( *func_ )( chr, msg );
346 }
347 
348 
350  : TargetCursor( true ), func_( func )
351 {
352 }
353 
354 void MultiPlacementCursor::send_placemulti( Network::Client* client, unsigned int objtype,
355  int flags, s16 xoffset, s16 yoffset, u32 hue )
356 {
358  msg->Write<u8>( 0x1u );
359  msg->WriteFlipped<u32>( cursorid_ );
360  msg->offset += 12; // 12x u8 unk
361  u16 multiid = Items::find_multidesc( objtype ).multiid;
362  multiid +=
363  static_cast<u16>( ( flags & Multi::CRMULTI_FACING_MASK ) >> Multi::CRMULTI_FACING_SHIFT );
364  msg->WriteFlipped<u16>( multiid );
365  msg->WriteFlipped<s16>( xoffset );
366  msg->WriteFlipped<s16>( yoffset );
367  msg->offset += 2; // u16 maybe_zoffset
368  if ( client->ClientType & Network::CLIENTTYPE_7090 )
369  msg->WriteFlipped<u32>( hue );
370  msg.Send( client );
371  client->chr->tcursor2 = this;
372 }
373 
375 {
376  ( *func_ )( chr, msg );
377 }
378 
379 
381  Mobile::Character* ) )
382  : TargetCursor( false /* don't inform on cancel */ ), func( func )
383 {
384 }
385 
387 {
388  if ( msgin == nullptr )
389  return;
390  u32 selected_serial = cfBEu32( msgin->selected_serial );
391  Mobile::Character* chr = find_character( selected_serial );
392  if ( chr != nullptr )
393  ( *func )( targetter, chr );
394 }
395 
397  bool inform_on_cancel )
398  : TargetCursor( inform_on_cancel ), func( func )
399 {
400 }
401 
403 {
404  if ( msgin == nullptr )
405  {
406  ( *func )( targetter, nullptr );
407  return;
408  }
409  u32 selected_serial = cfBEu32( msgin->selected_serial );
410 
411  UObject* obj = system_find_object( selected_serial );
412  if ( obj )
413  {
414  ( *func )( targetter, obj );
415  }
416  else if ( inform_on_cancel_ )
417  {
418  ( *func )( targetter, nullptr );
419  }
420 }
421 
423  : _target_cursors(), // NOTE: the id is 1-based (seems that the stealth client has problem with
424  // serial==0)
425  _cursorid_count(
426  1 ), // array and index needs to be initialized before registering the cursors
427  los_checked_script_cursor( Module::handle_script_cursor, true ),
428  nolos_checked_script_cursor( Module::handle_script_cursor, true ),
429 
430  add_member_cursor( handle_add_member_cursor ),
431  remove_member_cursor( handle_remove_member_cursor ),
432  ident_cursor( handle_ident_cursor ),
433  script_cursor2( Module::handle_coord_cursor, true ),
434  multi_placement_cursor( Module::handle_coord_cursor ),
435  repdata_cursor( show_repdata ),
436  startlog_cursor( start_packetlog ),
437  stoplog_cursor( stop_packetlog )
438 {
439 }
440 }
441 }
void handle_script_cursor(Character *chr, UObject *obj)
Definition: uomod.cpp:765
unsigned char u8
Definition: rawtypes.h:25
void cancel(Mobile::Character *chr)
Definition: target.cpp:152
void handle_target_cursor(Mobile::Character *targetter, PKTBI_6C *msg)
Definition: target.cpp:159
void handle_target_cursor(Network::Client *client, PKTBI_6C *msg)
Definition: target.cpp:37
UObject * system_find_object(u32 serial)
Definition: fnsearch.cpp:23
void start_packetlog(Mobile::Character *looker, Mobile::Character *mob)
Definition: textcmd.cpp:318
LosCheckedTargetCursor(void(*func)(Mobile::Character *, UObject *), bool inform_on_cancel=false)
Definition: target.cpp:230
void stop_packetlog(Mobile::Character *looker, Mobile::Character *mob)
Definition: textcmd.cpp:369
Network::Client * client
Definition: charactr.h:871
Cursors target_cursors
Definition: uvars.h:234
MultiPlacementCursor(void(*func)(Mobile::Character *, PKTBI_6C *msg))
Definition: target.cpp:349
const int CRMULTI_FACING_MASK
Definition: multi.h:52
virtual void on_target_cursor(Mobile::Character *, PKTBI_6C *msg) POL_OVERRIDE
Definition: target.cpp:374
#define cfBEu32(x)
Definition: clib_endian.h:43
bool target_cursor_busy() const
Definition: charactr.cpp:4098
void show_repdata(Mobile::Character *looker, Mobile::Character *mob)
Definition: textcmd.cpp:306
NoLosCharacterCursor(void(*func)(Mobile::Character *targetter, Mobile::Character *targetted))
Definition: target.cpp:380
bool is_visible_to_me(const Character *chr) const
Definition: charactr.cpp:2658
Core::TargetCursor * tcursor2
Definition: charactr.h:861
TargetCursor(bool inform_on_cancel)
Definition: target.cpp:115
bool frozen() const
Definition: charactr.h:969
Item * find_legal_item(const Character *chr, u32 serial, bool *additlegal, bool *isRemoteContainer)
Definition: ufunc.cpp:958
void(* func)(Mobile::Character *targetter, PKTBI_6C *msg)
Definition: target.h:69
void handle_ident_cursor(Mobile::Character *chr, PKTBI_6C *msgin)
Definition: textcmd.cpp:213
#define POLLOG_ERROR
Definition: logfacility.h:207
unsigned short multiid
Definition: itemdesc.h:128
virtual bool script_isa(unsigned isatype) const
Definition: uoscrobj.cpp:4566
Mobile::Character * chr
Definition: client.h:182
bool can_freemove() const
Definition: charactr.cpp:1271
bool private_say_above(Character *chr, const UObject *obj, const char *text, unsigned short font, unsigned short color, unsigned int journal_print)
Definition: ufunc.cpp:1328
unsigned short u16
Definition: rawtypes.h:26
unsigned int u32
Definition: rawtypes.h:27
void(* func)(Mobile::Character *, UObject *targetted)
Definition: target.h:88
Multi::UMulti * system_find_multi(u32 serial)
Definition: fnsearch.cpp:50
bool send_coord_cursor(Network::Client *client)
Definition: target.cpp:324
signed short s16
Definition: rawtypes.h:30
virtual void on_target_cursor(Mobile::Character *, PKTBI_6C *msg) POL_OVERRIDE
Definition: target.cpp:285
LosCheckedCoordCursor(void(*func)(Mobile::Character *, PKTBI_6C *msg), bool inform_on_cancel=false)
Definition: target.cpp:318
virtual void on_target_cursor(Mobile::Character *targetter, PKTBI_6C *msg) POL_OVERRIDE
Definition: target.cpp:223
void Send(Client *client, int len=-1) const
Definition: packethelper.h:69
bool has_los(const Core::ULWObject &att, const Core::ULWObject &tgt) const
Definition: realmlos.cpp:146
bool paralyzed() const
Definition: charactr.h:974
void(* func_)(Mobile::Character *, PKTBI_6C *)
Definition: target.h:129
virtual UObject * toplevel_owner()
Definition: uobject.cpp:234
const unsigned POLCLASS_MOBILE
Definition: polclass.h:15
GameState gamestate
Definition: uvars.cpp:74
u32 target_cursor_serial
Definition: pktboth.h:209
Mobile::Character * find_character(u32 serial)
Definition: fnsearch.cpp:60
const int CRMULTI_FACING_SHIFT
Definition: multi.h:53
void send_placemulti(Network::Client *client, unsigned int objtype, int flags, s16 xoffset, s16 yoffset, u32 hue)
Definition: target.cpp:354
void handle_add_member_cursor(Mobile::Character *chr, PKTBI_6C *msgin)
Definition: party.cpp:986
virtual void on_target_cursor(Mobile::Character *targetter, PKTBI_6C *msg)=0
void handle_remove_member_cursor(Mobile::Character *chr, PKTBI_6C *msgin)
Definition: party.cpp:1009
virtual void on_target_cursor(Mobile::Character *chr, PKTBI_6C *msg) POL_OVERRIDE
Definition: target.cpp:402
NoLosUObjectCursor(void(*func)(Mobile::Character *, UObject *), bool inform_on_cancel=false)
Definition: target.cpp:396
Core::AccountRef acct
Definition: charactr.h:914
FullMsgTargetCursor(void(*func)(Mobile::Character *, PKTBI_6C *))
Definition: target.cpp:218
const MultiDesc & find_multidesc(u32 objtype)
Definition: itemdesc.cpp:958
std::array< TargetCursor *, 10 > _target_cursors
Definition: target.h:214
Realms::Realm * realm
Definition: baseobject.h:56
bool send_object_cursor(Network::Client *client, PKTBI_6C::CURSOR_TYPE crstype=PKTBI_6C::CURSOR_TYPE_NEUTRAL)
Definition: target.cpp:133
static bool RunNoCombatCheck(Network::Client *client)
Definition: guardrgn.cpp:88
virtual void on_target_cursor(Mobile::Character *, PKTBI_6C *msg) POL_OVERRIDE
Definition: target.cpp:386
virtual void on_target_cursor(Mobile::Character *, PKTBI_6C *msg) POL_OVERRIDE
Definition: target.cpp:236
virtual std::string name() const
Definition: uobject.cpp:196
virtual void on_target_cursor(Mobile::Character *, PKTBI_6C *msg) POL_OVERRIDE
Definition: target.cpp:343
NoLosCheckedTargetCursor(void(*func)(Mobile::Character *, UObject *), bool inform_on_cancel=false)
Definition: target.cpp:279
Definition: berror.cpp:12
void handle_coord_cursor(Character *chr, PKTBI_6C *msg)
Definition: uomod.cpp:884
const unsigned POLCLASS_NPC
Definition: polclass.h:16
bool dead() const
Definition: charactr.h:931
void send_sysmessage(Network::Client *client, const char *text, unsigned short font, unsigned short color)
Definition: ufunc.cpp:1147
void(* func)(Mobile::Character *, UObject *targetted)
Definition: target.h:108
void(* func)(Mobile::Character *targetter, Mobile::Character *targetted)
Definition: target.h:170
UObject * find_toplevel_object(u32 serial)
Definition: fnsearch.cpp:86