1 /////////////////////////////////////////////////////////////////////////////// 2 // Copyright (C) 2004-2010 by The Allacrost Project 3 // All Rights Reserved 4 // 5 // This code is licensed under the GNU GPL version 2. It is free software 6 // and you may modify it and/or redistribute it under the terms of this license. 7 // See http://www.gnu.org/copyleft/gpl.html for details. 8 /////////////////////////////////////////////////////////////////////////////// 9 10 /** **************************************************************************** 11 *** \file map_sprites.h 12 *** \author Tyler Olsen, roots@allacrost.org 13 *** \brief Header file for map mode sprite code. 14 *** *****************************************************************************/ 15 16 #ifndef __MAP_SPRITES_HEADER__ 17 #define __MAP_SPRITES_HEADER__ 18 19 // Allacrost utilities 20 #include "utils.h" 21 #include "defs.h" 22 23 // Allacrost engines 24 #include "video.h" 25 26 #include "battle_events.h" 27 28 // Local map mode headers 29 #include "map_utils.h" 30 #include "map_objects.h" 31 #include "map_dialogue.h" 32 #include "map_zones.h" 33 34 namespace hoa_map { 35 36 namespace private_map { 37 38 /** **************************************************************************** 39 *** \brief A special type of sprite with no physical image 40 *** 41 *** The VirtualSprite is a special type of MapObject because it has no physical 42 *** form (no image). Virtual sprites may be manipulated to move around on the screen 43 *** just like any other sprite. VirtualSprites do take collision detection into account 44 *** by default, unless the no_collision member is set to true. Here are some examples of 45 *** where virtual sprites may be of use: 46 *** 47 *** - As a mobile focusing point for the map camera 48 *** - As an impassible map location for ground objects in a specific context only 49 *** - To set impassible locations for objects in the sky layer 50 *** 51 *** \note The VirtualSprite class serves as a base class for all other types of 52 *** sprites. 53 *** ***************************************************************************/ 54 class VirtualSprite : public MapObject { 55 public: 56 VirtualSprite(); 57 58 ~VirtualSprite(); 59 60 // ---------- Public Members: Orientation and Movement 61 62 /** \brief A bit-mask for the sprite's draw orientation and direction vector. 63 *** This member determines both where to move the sprite (8 directions) and 64 *** which way the sprite is facing (4 directions). See the Sprite direction 65 *** constants for the values that this member may be set to. 66 **/ 67 uint16 direction; 68 69 //! \brief The speed at which the sprite moves around the map. 70 float movement_speed; 71 72 /** \brief Set to true when the sprite is currently in motio. 73 *** This does not necessarily mean that the sprite actually is moving, but rather 74 *** that the sprite is <i>trying</i> to move in a certain direction. 75 **/ 76 bool moving; 77 78 /** \brief Set to true whenever the sprite's position was changed due to movement 79 *** This is distinctly different than the moving member. Whereas the moving member 80 *** indicates desired movement, this member indicates that positionaly change due to 81 *** movement actually occurred. It is used for drawing functions to determine if they 82 *** should draw the sprite in motion or not in motion 83 **/ 84 bool moved_position; 85 86 //! \brief Set to true when the sprite is running rather than walking 87 bool is_running; 88 89 // ---------- Public Members: Events 90 91 //! \brief A pointer to the event that is controlling the action of this sprite 92 SpriteEvent* control_event; 93 94 // ---------- Public methods 95 96 //! \brief Updates the virtual object's position if it is moving, otherwise does nothing. 97 virtual void Update(); 98 99 //! \brief Does nothing since virtual sprites have no image to draw Draw()100 virtual void Draw() 101 {} 102 103 /** \note This method takes into account the current direction when setting the new direction 104 *** in the case of diagonal movement. For example, if the sprite is currently facing north 105 *** and this function indicates that the sprite should move northwest, it will face north 106 *** during the northwest movement. 107 **/ 108 void SetDirection(uint16 dir); 109 110 /** \brief Sets the sprite's direction to a random value 111 *** This function is used mostly for the ActionRandomMove class. 112 **/ 113 void SetRandomDirection(); 114 115 /** \brief Calculates the distance the sprite should move given its velocity (speed and direction) 116 *** \return A floating point value representing the distance moved 117 *** \note This method does not check if the "moving" member is true but does factor in the "is_running" 118 *** member in its calculation. 119 **/ 120 float CalculateDistanceMoved(); 121 122 /** \brief Declares that an event is taking control over the sprite 123 *** \param event The sprite event that is assuming control 124 *** This function is not safe to call when there is an event already controlling the sprite. 125 *** The previously controlling event should first release control (which will set the control_event 126 *** member to NULL) before a new event acquires it. The acquisition will be successful regardless 127 *** of whether there is currently a controlling event or not, but a warning will be printed in the 128 *** improper case. 129 **/ 130 void AcquireControl(SpriteEvent* event); 131 132 /** \brief Declares that an event is releasing control over the sprite 133 *** \param event The sprite event that is releasing control 134 *** The reason why the SpriteEvent has to pass a pointer to itself in this call is to make sure 135 *** that this event is still controlling the sprite. If the control has switched to another event 136 *** (because another event acquired it before this event released it), a warning will be printed 137 *** and no change will be made (the control event will not change). 138 **/ 139 void ReleaseControl(SpriteEvent* event); 140 141 /** \brief Saves the state of the sprite 142 *** Attributes saved: direction, speed, moving state 143 **/ 144 virtual void SaveState(); 145 146 /** \brief Restores the saved state of the sprite 147 *** Attributes restored: direction, speed, moving state 148 **/ 149 virtual void RestoreState(); 150 151 /** \name Lua Access Functions 152 *** These functions are specifically written to enable Lua to access the members of this class. 153 **/ 154 //@{ IsStateSaved()155 bool IsStateSaved() const 156 { return _state_saved; } 157 SetMovementSpeed(float speed)158 void SetMovementSpeed(float speed) 159 { movement_speed = speed; } 160 GetDirection()161 uint16 GetDirection() const 162 { return direction; } 163 GetMovementSpeed()164 float GetMovementSpeed() const 165 { return movement_speed; } 166 //@} 167 168 protected: 169 /** \brief Determines an appropriate resolution when the sprite collides with an obstruction 170 *** \param coll_type The type of collision that has occurred 171 *** \param coll_obj A pointer to the MapObject that the sprite has collided with, if any 172 **/ 173 void _ResolveCollision(COLLISION_TYPE coll_type, MapObject* coll_obj); 174 175 /** \name Saved state attributes 176 *** These attributes are used to save and restore the state of a VirtualSprite 177 **/ 178 //@{ 179 //! \brief Indicates if the other saved members are valid because the state has recently been saved 180 bool _state_saved; 181 uint16 _saved_direction; 182 float _saved_movement_speed; 183 bool _saved_moving; 184 //@} 185 }; // class VirtualSprite : public MapObject 186 187 188 /** **************************************************************************** 189 *** \brief A mobile map object with which the player can interact with. 190 *** 191 *** Map sprites are animate, mobile, living map objects. Although there is 192 *** but this single class to represent all the map sprites in the game, they can 193 *** divided into types such as NPCs, friendly creatures, and enemies. The fact 194 *** that there is only one class for representing several sprite types is the 195 *** reason why many of the class members are pointers. For example, we don't 196 *** need dialogue for a dog sprite. 197 *** ***************************************************************************/ 198 class MapSprite : public VirtualSprite { 199 public: 200 MapSprite(); 201 202 ~MapSprite(); 203 204 // ---------- Public methods 205 206 /** \brief Loads the image containing the standard animations for the sprite 207 *** \param filename The name of the image file holding the standard walking animations 208 *** \return False if there was a problem loading the sprite. 209 **/ 210 bool LoadStandardAnimations(std::string filename); 211 212 /** \brief Loads the image containing the running animations for the sprite 213 *** \param filename The name of the image file 214 *** \return False if the animations were not created successfully. 215 **/ 216 bool LoadRunningAnimations(std::string filename); 217 218 /** \brief Loads the image containing the attack animations for the sprite 219 *** \param filename The name of the image file 220 *** \return False if the animations were not created successfully. 221 **/ 222 bool LoadAttackAnimations(std::string filename); 223 224 void LoadFacePortrait(std::string pn); 225 226 //! \brief Updates the sprite's position and state. 227 virtual void Update(); 228 229 //! \brief Draws the sprite frame in the appropriate position on the screen, if it is visible. 230 virtual void Draw(); 231 232 /** \brief Adds a new reference to a dialogue that the sprite uses 233 *** \param dialogue_id The ID number of the dialogue 234 *** \note It is valid for a dialogue to be referenced more than once by a sprite 235 **/ 236 void AddDialogueReference(uint32 dialogue_id); 237 238 //! \brief Updates all dialogue status members based on the status of all referenced dialogues 239 void UpdateDialogueStatus(); 240 241 //! \brief Increments the next_dialogue member to index the proceeding dialogue 242 void IncrementNextDialogue(); 243 244 /** \brief Sets the next dialogue member for the sprite 245 *** \param next The index value of the dialogue_references vector to set the next_dialogue member to 246 *** \note You can not set the next_dialogue member to a negative number. This could cause run-time errors if it was supported here. 247 **/ 248 void SetNextDialogue(uint16 next); 249 250 /** \brief This method will save the state of a sprite. 251 *** Attributes saved: direction, speed, moving state, name 252 *** current animation. 253 **/ 254 virtual void SaveState(); 255 256 /** \brief This method will load the saved state of a sprite. 257 *** Attributes loaded: direction, speed, moving state, name 258 *** current animation. 259 *** \return false if there was no saved state, true otherwise. 260 **/ 261 virtual void RestoreState(); 262 263 /** \name Lua Access Functions 264 *** These functions are specifically written to enable Lua to access the members of this class. 265 **/ 266 //@{ 267 // TODO: needs to be a ustring SetName(std::string na)268 void SetName(std::string na) 269 { _name = hoa_utils::MakeUnicodeString(na); } 270 SetCurrentAnimation(uint8 anim)271 void SetCurrentAnimation(uint8 anim) 272 { _current_animation = anim; } 273 GetCurrentAnimation()274 uint8 GetCurrentAnimation() const 275 { return _current_animation; } 276 HasAvailableDialogue()277 bool HasAvailableDialogue() const 278 { return _has_available_dialogue; } 279 HasUnseenDialogue()280 bool HasUnseenDialogue() const 281 { return _has_unseen_dialogue; } 282 GetName()283 hoa_utils::ustring& GetName() 284 { return _name; } 285 GetFacePortrait()286 hoa_video::StillImage* GetFacePortrait() const 287 { return _face_portrait; } 288 289 //! \brief Returns the next dialogue to reference (negative value returned if no dialogues are referenced) GetNextDialogue()290 int16 GetNextDialogue() const 291 { return _next_dialogue; } 292 293 //! \brief Gets the ID value of the dialogue that will be the next to be referenced by the sprite GetNextDialogueID()294 uint32 GetNextDialogueID() const // TODO: check invalid indexing 295 { return _dialogue_references[_next_dialogue]; } 296 297 //! \brief Returns the number of dialogues referenced by the sprite (including duplicates) GetNumberDialogueReferences()298 uint16 GetNumberDialogueReferences() const 299 { return _dialogue_references.size(); } 300 301 //! \brief Set to true for a custom animation SetCustomAnimation(bool on_or_off)302 void SetCustomAnimation(bool on_or_off) 303 { _custom_animation_on = on_or_off; } 304 //@} 305 306 307 protected: 308 //! \brief The name of the sprite, as seen by the player in the game. 309 hoa_utils::ustring _name; 310 311 /** \brief A pointer to the face portrait of the sprite, as seen in dialogues and menus. 312 *** \note Not all sprites have portraits, in which case this member will be NULL 313 **/ 314 hoa_video::StillImage* _face_portrait; 315 316 //! \brief Set to true if the sprite has running animations loaded 317 bool _has_running_animations; 318 319 //! \brief The index to the animations vector containing the current sprite image to display 320 uint8 _current_animation; 321 322 /** \brief A vector containing all the sprite's various animations. 323 *** The first four entries in this vector are the walking animation frames. 324 *** They are ordered from index 0 to 3 as: down, up, left, right. Additional 325 *** animations may follow. 326 **/ 327 std::vector<hoa_video::AnimatedImage> _animations; 328 329 //! \brief Contains the id values of all dialogues refenced by the sprite 330 std::vector<uint32> _dialogue_references; 331 332 /** \brief An index to the dialogue_references vector, representing the next dialogue the sprite should reference 333 *** A negative value indicates that the sprite has no dialogue. 334 **/ 335 int16 _next_dialogue; 336 337 /** \brief True is sprite references at least one available dialogue 338 *** \note A dialogue may become unavailable if it reaches its max view count 339 **/ 340 bool _has_available_dialogue; 341 342 //! \brief True if at least one dialogue referenced by this sprite has not yet been viewed -and- is available to be viewed 343 bool _has_unseen_dialogue; 344 345 //! \brief True if a custom animation is in use 346 bool _custom_animation_on; 347 348 /** \name Saved state attributes 349 *** These attributes are used to save and load the state of a VirtualSprite 350 **/ 351 //@{ 352 uint8 _saved_current_animation; 353 //@} 354 }; // class MapSprite : public VirtualSprite 355 356 357 /** **************************************************************************** 358 *** \brief A mobile map object that induces a battle to occur if the player touches it 359 *** 360 *** There are really two types of enemy sprites. The first type behave just like 361 *** map sprites and can have scripted movement sequences. The second type belong 362 *** to EnemyZones, where they fade into existence and pursue after the player's 363 *** sprite should the player enter the zone. 364 *** 365 *** An enemy sprite in a zone can be in one of 3 states: SPAWNING, HOSTILE or DEAD. 366 *** In the spawning state, the enemy becomes gradually visible, is immobile, and 367 *** cannot be touched or attacked. In the hostile state, the enemies roams the map 368 *** and will cause a battle if touched by the player. In the dead state, the enemy 369 *** is invisible and waits for the EnemyZone to reset it in another position, so 370 *** that it may spawn once more. 371 *** ***************************************************************************/ 372 class EnemySprite : public MapSprite { 373 private: 374 //! \brief The states that the enemy sprite may be in 375 enum STATE { 376 SPAWNING, 377 HOSTILE, 378 DEAD 379 }; 380 381 public: 382 383 std::string filename; 384 385 //! \brief The default constructor which typically requires that the user make several additional calls to setup the sprite properties 386 EnemySprite(); 387 388 //! \brief A constructor for when the enemy sprite is stored in the definition of a single file 389 EnemySprite(std::string file); 390 391 //! \brief Loads the enemy's data from a file and returns true if it was successful 392 bool Load(); 393 394 //! \brief Resets various members of the class so that the enemy is dead, invisible, and does not produce a collision 395 void Reset(); 396 397 //! \brief Updates the sprite's position and state. 398 virtual void Update(); 399 400 //! \brief Draws the sprite frame in the appropriate position on the screen, if it is visible. 401 virtual void Draw(); 402 403 // TODO: eventually I would like the ability for Lua to pass in a table of ints to the AddEnemyParty function, but because I'm not quite 404 // sure how to do that yet, I'm writing several smaller functions so we can just get this demo released. 405 406 // void AddEnemyParty(std::vector<uint32>& party); 407 408 /** \brief Adds a new empty vector to the _enemy_parties member 409 *** \note Make sure to populate this vector by adding at least one enemy! 410 **/ NewEnemyParty()411 void NewEnemyParty() 412 { _enemy_parties.push_back(std::vector<uint32>()); } 413 414 /** \brief Adds an enemy with the specified ID to the last party in _enemy_parties 415 *** \param enemy_id The ID of the enemy to add 416 *** \note MapMode should have already loaded a GlobalEnemy with this ID and retained it within the MapMode#_enemies member. 417 *** If this is not the case, this function will print a warning message. 418 **/ 419 void AddEnemy(uint32 enemy_id); 420 421 //! \brief Returns a reference to a random party of enemies 422 const std::vector<uint32>& RetrieveRandomParty(); 423 424 //! \name Class Member Access Functions 425 //@{ GetAggroRange()426 float GetAggroRange() const 427 { return _aggro_range; } 428 GetTimeToChange()429 uint32 GetTimeToChange() const 430 { return _time_dir_change; } 431 GetTimeToSpawn()432 uint32 GetTimeToSpawn() const 433 { return _time_to_spawn; } 434 GetBattleMusicTheme()435 std::string GetBattleMusicTheme() const 436 { return _music_theme; } 437 GetBattleBackground()438 std::string GetBattleBackground() const 439 { return _bg_file; } 440 IsDead()441 bool IsDead() const 442 { return _state == DEAD; } 443 IsSpawning()444 bool IsSpawning() const 445 { return _state == SPAWNING; } 446 IsHostile()447 bool IsHostile() const 448 { return _state == HOSTILE; } 449 SetZone(EnemyZone * zone)450 void SetZone(EnemyZone* zone) 451 { _zone = zone; } 452 SetAggroRange(float range)453 void SetAggroRange(float range) 454 { _aggro_range = range; } 455 SetTimeToChange(uint32 time)456 void SetTimeToChange(uint32 time) 457 { _time_dir_change = time; } 458 SetTimeToSpawn(uint32 time)459 void SetTimeToSpawn(uint32 time) 460 { _time_to_spawn = time; } 461 SetBattleMusicTheme(const std::string & music_theme)462 void SetBattleMusicTheme(const std::string& music_theme) 463 { _music_theme = music_theme; } 464 SetBattleBackground(const std::string & bg_file)465 void SetBattleBackground(const std::string& bg_file) 466 { _bg_file = bg_file; } 467 ChangeStateDead()468 void ChangeStateDead() 469 { Reset(); if (_zone) _zone->EnemyDead(); } 470 ChangeStateSpawning()471 void ChangeStateSpawning() 472 { updatable = true; _state = SPAWNING; no_collision = false; } 473 ChangeStateHostile()474 void ChangeStateHostile() 475 { updatable = true; _state = HOSTILE; no_collision = false; _color.SetAlpha(1.0); } 476 AddBattleEvent(uint32 n)477 void AddBattleEvent(uint32 n) 478 { hoa_battle::BattleEvent* thisEvent = new hoa_battle::BattleEvent(n); _battle_events.push_back(thisEvent); } 479 GetBattleEvents()480 std::vector<hoa_battle::BattleEvent*> GetBattleEvents() { return _battle_events; } 481 //@} 482 483 private: 484 //! \brief The zone that the enemy sprite belongs to 485 private_map::EnemyZone* _zone; 486 487 //! \brief Used to gradually fade in the sprite as it is spawning by adjusting the alpha channel 488 hoa_video::Color _color; 489 490 //! \brief A timer used for spawning 491 uint32 _time_elapsed; 492 493 //! \brief The state that the enemy sprite is in 494 STATE _state; 495 496 //! \brief A value which determines how close the player needs to be for the enemy to aggressively seek to confront it 497 float _aggro_range; 498 499 //! \brief ??? 500 uint32 _time_dir_change; 501 502 //! \brief ??? 503 uint32 _time_to_spawn; 504 505 //! \brief Indicates if the enemy is outside of its zone. If it is, it won't change direction until it gets back in. 506 bool _out_of_zone; 507 508 //! \brief The default battle music theme for the monster 509 std::string _music_theme; 510 511 //! \brief The default background for the battle 512 std::string _bg_file; 513 514 /** \brief Contains the possible groups of enemies that may appear in a battle should the player encounter this enemy sprite 515 *** The numbers contained within this member are ID numbers for the enemy. If the 516 **/ 517 std::vector<std::vector<uint32> > _enemy_parties; 518 519 //! \brief Vector containing custom scripts for this battle 520 std::vector<hoa_battle::BattleEvent*> _battle_events; 521 }; // class EnemySprite : public MapSprite 522 523 } // namespace private_map 524 525 } // namespace hoa_map 526 527 #endif // __MAP_SPRITES_HEADER__ 528