1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (C) 2004-2011 by The Allacrost Project
3 // Copyright (C) 2012-2016 by Bertram (Valyria Tear)
4 // All Rights Reserved
5 //
6 // This code is licensed under the GNU GPL version 2. It is free software
7 // and you may modify it and/or redistribute it under the terms of this license.
8 // See https://www.gnu.org/copyleft/gpl.html for details.
9 ///////////////////////////////////////////////////////////////////////////////
10
11 #include "modes/map/map_objects/map_treasure.h"
12
13 #include "modes/map/map_mode.h"
14 #include "modes/map/map_event_supervisor.h"
15
16 #include "common/global/global.h"
17
18 namespace vt_map
19 {
20
21 namespace private_map
22 {
23
TreasureObject(const std::string & treasure_name,MapObjectDrawLayer layer,const std::string & closed_animation_file,const std::string & opening_animation_file,const std::string & open_animation_file)24 TreasureObject::TreasureObject(const std::string& treasure_name,
25 MapObjectDrawLayer layer,
26 const std::string& closed_animation_file,
27 const std::string& opening_animation_file,
28 const std::string& open_animation_file) :
29 PhysicalObject(layer)
30 {
31 _object_type = TREASURE_TYPE;
32 _events_triggered = false;
33 _is_opening = false;
34
35 _treasure_name = treasure_name;
36 if(treasure_name.empty())
37 PRINT_WARNING << "Empty treasure name found. The treasure won't function normally." << std::endl;
38
39 _treasure = new vt_map::private_map::MapTreasureContent();
40
41 // Dissect the frames and create the closed, opening, and open animations
42 vt_video::AnimatedImage closed_anim, opening_anim, open_anim;
43
44 closed_anim.LoadFromAnimationScript(closed_animation_file);
45 if(!opening_animation_file.empty())
46 opening_anim.LoadFromAnimationScript(opening_animation_file);
47 open_anim.LoadFromAnimationScript(open_animation_file);
48
49 // Set the collision rectangle according to the dimensions of the first frame
50 SetCollPixelHalfWidth(closed_anim.GetWidth() / 2.0f);
51 SetCollPixelHeight(closed_anim.GetHeight());
52
53 // Apply the zoom ratio on the animations.
54 ScaleToMapZoomRatio(closed_anim);
55 ScaleToMapZoomRatio(opening_anim);
56 ScaleToMapZoomRatio(open_anim);
57
58 AddAnimation(closed_anim);
59 AddAnimation(opening_anim);
60 AddAnimation(open_anim);
61
62 _LoadState();
63 }
64
Create(const std::string & treasure_name,MapObjectDrawLayer layer,const std::string & closed_animation_file,const std::string & opening_animation_file,const std::string & open_animation_file)65 TreasureObject* TreasureObject::Create(const std::string &treasure_name,
66 MapObjectDrawLayer layer,
67 const std::string &closed_animation_file,
68 const std::string &opening_animation_file,
69 const std::string &open_animation_file)
70 {
71 // The object auto registers to the object supervisor
72 // and will later handle deletion.
73 return new TreasureObject(treasure_name, layer,
74 closed_animation_file,
75 opening_animation_file,
76 open_animation_file);
77 }
78
_LoadState()79 void TreasureObject::_LoadState()
80 {
81 if(!_treasure)
82 return;
83
84 // If the event exists, the treasure has already been opened
85 if(vt_global::GlobalManager->GetGameEvents().DoesEventExist("treasures", _treasure_name)) {
86 SetCurrentAnimation(TREASURE_OPEN_ANIM);
87 _treasure->SetTaken(true);
88 }
89 }
90
Open()91 void TreasureObject::Open()
92 {
93 if(!_treasure) {
94 PRINT_ERROR << "Can't open treasure with invalid treasure content." << std::endl;
95 return;
96 }
97
98 if(_treasure->IsTaken()) {
99 IF_PRINT_WARNING(MAP_DEBUG) << "attempted to retrieve an already taken treasure: " << _object_id << std::endl;
100 return;
101 }
102
103 // Test whether events should be triggered
104 if (_events.empty())
105 _events_triggered = true;
106
107 SetCurrentAnimation(TREASURE_OPENING_ANIM);
108 _is_opening = true;
109 }
110
Update()111 void TreasureObject::Update()
112 {
113 PhysicalObject::Update();
114
115 if ((GetCurrentAnimationId() == TREASURE_OPENING_ANIM) && (_animations[TREASURE_OPENING_ANIM].IsAnimationFinished()))
116 SetCurrentAnimation(TREASURE_OPEN_ANIM);
117
118 if (!_is_opening || GetCurrentAnimationId() != TREASURE_OPEN_ANIM)
119 return;
120
121 MapMode* mm = MapMode::CurrentInstance();
122
123 // Once opened, we handle potential events and the display of the treasure supervisor
124 EventSupervisor* event_manager = mm->GetEventSupervisor();
125
126 if (!_events_triggered) {
127 // Trigger potential events after opening
128 for (uint32_t i = 0; i < _events.size(); ++i) {
129 if (!event_manager->IsEventActive(_events[i]))
130 event_manager->StartEvent(_events[i]);
131 }
132 _events_triggered = true;
133 }
134 else if (!_events.empty()) {
135 // Test whether the events have finished
136 std::vector<std::string>::iterator it = _events.begin();
137 for (; it != _events.end();) {
138 // Once the event has finished, we forget it
139 if (!event_manager->IsEventActive(*it))
140 it = _events.erase(it);
141 else
142 ++it;
143 }
144 }
145 else {
146 // Once all events are finished, we can open the treasure supervisor
147 mm->GetTreasureSupervisor()->Initialize(this);
148 // Add an event to the treasures group indicating that the treasure has now been opened
149 vt_global::GlobalManager->GetGameEvents().SetEventValue("treasures", _treasure_name, 1);
150 // End the opening sequence
151 _is_opening = false;
152 }
153 }
154
AddItem(uint32_t id,uint32_t quantity)155 bool TreasureObject::AddItem(uint32_t id, uint32_t quantity)
156 {
157 if(!_treasure)
158 return false;
159 return _treasure->AddItem(id, quantity);
160 }
161
AddEvent(const std::string & event_id)162 void TreasureObject::AddEvent(const std::string& event_id)
163 {
164 if (!event_id.empty())
165 _events.push_back(event_id);
166 }
167
168 } // namespace private_map
169
170 } // namespace vt_map
171