Actor.pm.svn-base
上传用户:market2
上传日期:2018-11-18
资源大小:18786k
文件大小:10k
源码类别:

外挂编程

开发平台:

Windows_Unix

  1. #########################################################################
  2. #  OpenKore - Base class for all actor objects
  3. #  Copyright (c) 2005 OpenKore Team
  4. #
  5. #  This software is open source, licensed under the GNU General Public
  6. #  License, version 2.
  7. #  Basically, this means that you're allowed to modify and distribute
  8. #  this software. However, if you distribute modified versions, you MUST
  9. #  also distribute the source code.
  10. #  See http://www.gnu.org/licenses/gpl.html for the full license.
  11. #
  12. #  $Revision$
  13. #  $Id$
  14. #
  15. #########################################################################
  16. ##
  17. # MODULE DESCRIPTION: Base class for all actor objects
  18. #
  19. # The Actor class is a base class for all actor objects.
  20. # An actor object is a monster or player (all members of %monsters and
  21. # %players). Do not create an object of this class; use one of the
  22. # subclasses instead.
  23. #
  24. # An actor object is also a hash.
  25. #
  26. # Child classes: @MODULE(Actor::Monster), @MODULE(Actor::Player), @MODULE(Actor::You),
  27. # @MODULE(Actor::Item), @MODULE(Actor::Pet), @MODULE(Actor::Party), @MODULE(Actor::NPC),
  28. # @MODULE(Actor::Portal)
  29. package Actor;
  30. use strict;
  31. use Carp::Assert;
  32. use Scalar::Util;
  33. use Data::Dumper;
  34. use Storable;
  35. use Globals;
  36. use Utils;
  37. use Utils::CallbackList;
  38. use Log qw(message error debug);
  39. use Misc;
  40. # Make it so that
  41. #     print $actor;
  42. # acts the same as
  43. #     print $actor->nameString;
  44. use overload '""' => &_nameString;
  45. # The eq operator checks whether two variables refer to compatible objects.
  46. use overload 'eq' => &_eq;
  47. use overload 'ne' => &_ne;
  48. # The == operator is to check whether two variables refer to the
  49. # exact same object.
  50. use overload '==' => &_isis;
  51. use overload '!=' => &_not_is;
  52. sub _eq {
  53. return UNIVERSAL::isa($_[0], "Actor")
  54. && UNIVERSAL::isa($_[1], "Actor")
  55. && $_[0]->{ID} eq $_[1]->{ID};
  56. }
  57. sub _ne {
  58. return !&_eq;
  59. }
  60. # This function is needed to make the operator overload respect inheritance.
  61. sub _nameString {
  62. my $self = shift;
  63. return $self->nameString(@_);
  64. }
  65. sub _isis {
  66. return Scalar::Util::refaddr($_[0]) == Scalar::Util::refaddr($_[1]);
  67. }
  68. sub _not_is {
  69. return !&_isis;
  70. }
  71. ### CATEGORY: Class methods
  72. # protected Actor->new(String actorType)
  73. # actorType: A type name for this actor, like 'Player', 'Monster', etc.
  74. # Requires: defined($actorType)
  75. #
  76. # A default abstract constructor that subclasses should call. Must not
  77. # be directly used.
  78. sub new {
  79. my ($class, $actorType) = @_;
  80. my %self = (
  81. actorType => $actorType,
  82. onNameChange => new CallbackList('onNameChange'),
  83. onUpdate => new CallbackList('onUpdate')
  84. );
  85. return bless %self, $class;
  86. }
  87. ##
  88. # Actor Actor::get(Bytes ID)
  89. # ID: an actor ID, in binary format.
  90. # Returns: the associated Actor object, or a new Actor::Unknown object if not found.
  91. # Requires: defined($ID)
  92. # Ensures:  defined(result)
  93. #
  94. # Returns the Actor object for $ID. This function will look at the various
  95. # actor lists. If $ID is not in any of the actor lists, it will return
  96. # a new Actor::Unknown object.
  97. sub get {
  98. my ($ID) = @_;
  99. assert(defined $ID) if DEBUG;
  100. if ($ID eq $accountID || $ID eq "00000000") {
  101. # I put assertions here because $char seems to be unblessed sometimes.
  102. assert(defined $char, '$char must be defined') if DEBUG;
  103. assert(UNIVERSAL::isa($char, 'Actor::You'), '$char must be of class Actor::You') if DEBUG;
  104. return $char;
  105. } elsif ($items{$ID}) {
  106. return $items{$ID};
  107. } else {
  108. foreach my $list ($playersList, $monstersList, $npcsList, $petsList, $portalsList, $slavesList) {
  109. my $actor = $list->getByID($ID);
  110. if ($actor) {
  111. return $actor;
  112. }
  113. }
  114. return new Actor::Unknown($ID);
  115. }
  116. }
  117. ### CATEGORY: Hash members
  118. ##
  119. # String $Actor->{actorType}
  120. # Invariant: defined(value)
  121. #
  122. # An identifier for this actor's type. The meaning for this field
  123. # depends on the actor's class. For example, for Player actors,
  124. # this is the job ID (though you should use $ActorPlayer->{jobID} instead).
  125. ##
  126. # int $Actor->{binID}
  127. # Invariant: value >= 0
  128. #
  129. # The index of this actor inside its associated actor list.
  130. ##
  131. # Bytes $Actor->{ID}
  132. # Invariant: length(value) == 4
  133. #
  134. # The server's internal unique ID for this actor (the actor's account ID).
  135. ##
  136. # int $Actor->{nameID}
  137. # Invariant: value >= 0
  138. #
  139. # $Actor->{ID} decoded into an 32-bit little endian integer.
  140. ##
  141. # int $Actor->{appear_time}
  142. # Invariant: value >= 0
  143. #
  144. # The time when this actor first appeared on screen.
  145. ##
  146. # String $Actor->{actorType}
  147. # Invariant: defined(value)
  148. #
  149. # A human-friendly name which describes this actor type.
  150. # For instance, "Player", "Monster", "NPC", "You", etc.
  151. # Do not confuse this with $Actor->{type}
  152. ##
  153. # String $Actor->{name}
  154. #
  155. # The name of the actor, e.g. "Joe", "Jane", "Poring", etc.
  156. # This field is undefined if the name for this actor isn't known yet,
  157. # so generally you use use $Actor->name() instead, which automatically
  158. # takes care of actor objects that don't have a name yet.
  159. ##
  160. # Hash* $Actor->{pos}
  161. #
  162. # The position where this actor was, before its last movement.
  163. # This is a reference to a hash, containing the items 'x' and 'y'.
  164. ##
  165. # Hash* $Actor->{pos_to}
  166. #
  167. # The position where this actor is moving to, or (if the actor has finished moving),
  168. # where it currently is. This is a reference to a hash, containing the items 'x' and 'y'.
  169. ##
  170. # float $Actor->{walk_speed}
  171. #
  172. # The actor's walking speed, in blocks per second.
  173. ##
  174. # float $Actor->{time_move}
  175. #
  176. # The time (as timestamp) at which the actor last moved.
  177. ##
  178. # float $Actor->{time_move_calc}
  179. #
  180. # The time (in seconds) that the actor needs to move from $Actor->{pos} to $Actor->{pos_to}.
  181. ### CATEGORY: Methods
  182. ##
  183. # String $Actor->nameString([Actor otherActor])
  184. #
  185. # Returns the name string of an actor, e.g. "Player pmak (3)",
  186. # "Monster Poring (0)" or "You".
  187. #
  188. # If $otherActor is specified and is equal to $actor, then it will
  189. # return 'self' or 'yourself' instead.
  190. sub nameString {
  191. my ($self, $otherActor) = @_;
  192. return $self->selfString if $self->{ID} eq $otherActor->{ID};
  193. my $nameString = "$self->{actorType} " . $self->name;
  194. $nameString .= " ($self->{binID})" if defined $self->{binID};
  195. return $nameString;
  196. }
  197. ##
  198. # String $Actor->selfString()
  199. #
  200. # Returns 'itself' for monsters, or 'himself/herself' for players.
  201. # ('yourself' is handled by Actor::You.nameString.)
  202. sub selfString {
  203. return 'itself';
  204. }
  205. ##
  206. # String $Actor->name()
  207. #
  208. # Returns the name of an actor, e.g. "pmak" or "Unknown #300001".
  209. sub name {
  210. my ($self) = @_;
  211. return $self->{name} || "Unknown #".unpack("V1", $self->{ID});
  212. }
  213. ##
  214. # void $Actor->setName(String name)
  215. # name: A few name for this actor. Can be undef to indicate that this actor has lost its previous name.
  216. #
  217. # Assign a name to this actor. An 'onNameChange' and 'onUpdate' event will
  218. # be triggered after the name is set.
  219. sub setName {
  220. my ($self, $name) = @_;
  221. my $oldName = $self->{name};
  222. $self->{name} = $name;
  223. $self->{onNameChange}->call($self, { oldName => $oldName });
  224. $self->{onUpdate}->call($self);
  225. }
  226. ##
  227. # String $Actor->nameIdx()
  228. #
  229. # Returns the name and index of an actor, e.g. "pmak (0)" or "Unknown #300001 (1)".
  230. sub nameIdx {
  231. my ($self) = @_;
  232. my $nameIdx = $self->name;
  233. $nameIdx .= " ($self->{binID})" if defined $self->{binID};
  234. return $nameIdx;
  235. # return $self->{name} || "Unknown #".unpack("V1", $self->{ID});
  236. }
  237. ##
  238. # String $Actor->verb(String you, String other)
  239. #
  240. # Returns $you if $actor is you; $other otherwise.
  241. sub verb {
  242. my ($self, $you, $other) = @_;
  243. return $you if $self->isa('Actor::You');
  244. return $other;
  245. }
  246. ##
  247. # Hash $Actor->position()
  248. #
  249. # Returns the position of the actor.
  250. sub position {
  251. my ($self) = @_;
  252. return calcPosition($self);
  253. }
  254. ##
  255. # float $Actor->distance([Actor otherActor])
  256. #
  257. # Returns the distance to another actor (defaults to yourself).
  258. sub distance {
  259. my ($self, $otherActor) = @_;
  260. $otherActor ||= $char;
  261. return Utils::distance($self->position, $otherActor->position);
  262. }
  263. ##
  264. # float $Actor->blockDistance([Actor otherActor])
  265. #
  266. # Returns the block distance to another actor (defaults to yourself).
  267. sub blockDistance {
  268. my ($self, $otherActor) = @_;
  269. $otherActor ||= $char;
  270. return Utils::blockDistance($self->position, $otherActor->position);
  271. }
  272. ##
  273. # boolean $Actor->snipable()
  274. #
  275. # Returns whether or not you have snipable LOS to the actor.
  276. sub snipable {
  277. my ($self) = @_;
  278. return checkLineSnipable($char->position, $self->position);
  279. }
  280. ##
  281. # Actor $Actor->deepCopy()
  282. # Ensures: defined(result)
  283. #
  284. # Create a deep copy of this actor object.
  285. sub deepCopy {
  286. my ($self) = @_;
  287. # Some fields cannot be deep copied by dclone() because they contain
  288. # function references, so we'll do that manually.
  289. # Delete fields that cannot be copied by dclone() and store
  290. # them in a temporary place.
  291. my %deepCopyFields;
  292. my %hashCopies;
  293. foreach my $field ('onNameChange', 'onUpdate') {
  294. $deepCopyFields{$field} = $self->{$field};
  295. delete $self->{$field};
  296. }
  297. # $actor->{casting} may be a hash which contains a reference to another
  298. # Actor object.
  299. foreach my $field ('casting') {
  300. if ($self->{$field}) {
  301. $hashCopies{$field} = $self->{$field};
  302. delete $self->{$field};
  303. }
  304. }
  305. my $copy;
  306. eval {
  307. $copy = Storable::dclone($_[0]);
  308. };
  309. if ($@ =~ /Can't store CODE items/) {
  310. die "Actor hash $self contains CODE items:n" .
  311. Dumper($self);
  312. } elsif ($@) {
  313. die $@;
  314. }
  315. # Restore the deleted fields in the original object,
  316. # and assign manually-created deep copies to the clone.
  317. foreach my $field (keys %deepCopyFields) {
  318. $self->{$field} = $deepCopyFields{$field};
  319. $copy->{$field} = $deepCopyFields{$field}->deepCopy;
  320. }
  321. foreach my $field (keys %hashCopies) {
  322. $self->{$field} = $hashCopies{$field};
  323. $copy->{$field} = {%{$hashCopies{$field}}};
  324. }
  325. return $copy;
  326. }
  327. ##
  328. # CallbackList $Actor->onNameChange()
  329. # Ensures: defined(result)
  330. #
  331. # Returns the onNameChange event callback list.
  332. # This event is triggered when the name of this actor has changed.
  333. sub onNameChange {
  334. return $_[0]->{onNameChange};
  335. }
  336. ##
  337. # CallbackList $Actor->onUpdate()
  338. # Ensures: defined(result)
  339. #
  340. # Returns the onUpdate event callback list.
  341. sub onUpdate {
  342. return $_[0]->{onUpdate};
  343. }
  344. 1;