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