1 /************************************************************************
2  *                                                                      *
3  *  FreeSynd - a remake of the classic Bullfrog game "Syndicate".       *
4  *                                                                      *
5  *   Copyright (C) 2013  Benoit Blancard <benblan@users.sourceforge.net>*
6  *                                                                      *
7  *    This program is free software;  you can redistribute it and / or  *
8  *  modify it  under the  terms of the  GNU General  Public License as  *
9  *  published by the Free Software Foundation; either version 2 of the  *
10  *  License, or (at your option) any later version.                     *
11  *                                                                      *
12  *    This program is  distributed in the hope that it will be useful,  *
13  *  but WITHOUT  ANY WARRANTY;  without even  the implied  warranty of  *
14  *  MERCHANTABILITY  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU  *
15  *  General Public License for more details.                            *
16  *                                                                      *
17  *    You can view the GNU  General Public License, online, at the GNU  *
18  *  project's  web  site;  see <http://www.gnu.org/licenses/gpl.html>.  *
19  *  The full text of the license is also included in the file COPYING.  *
20  *                                                                      *
21  ************************************************************************/
22 
23 #include "menus/agentselectorrenderer.h"
24 #include "gfx/screen.h"
25 #include "app.h"
26 #include "ped.h"
27 
28 const int AgentSelectorRenderer::kIpaBarWidth = 56;
29 const int AgentSelectorRenderer::kIpaBarHeight = 10;
30 const int AgentSelectorRenderer::kIpaBarLeft13 = 4;
31 const int AgentSelectorRenderer::kIpaBarLeft24 = 68;
32 const int AgentSelectorRenderer::kIpaBarTop12  = 48;
33 const int AgentSelectorRenderer::kIpaBarTop34  = 148;
34 const int AgentSelectorRenderer::kIpaYOffset = 14;
35 
36 /*!
37  *
38  */
hasClickedOnAgentSelector(int x,int y,SelectorEvent & evt)39 bool AgentSelectorRenderer::hasClickedOnAgentSelector(int x, int y, SelectorEvent & evt) {
40     evt.eventType = SelectorEvent::kNone;
41     if (y < 46) {
42         evt.eventType = SelectorEvent::kSelectAgent;
43         if (x < 64) {
44             evt.agentSlot = 0;
45         } else {
46             evt.agentSlot = 1;
47         }
48     }
49 
50     else if (y >= 42 + 48 + 10 && y < 42 + 48 + 10 + 46) {
51         evt.eventType = SelectorEvent::kSelectAgent;
52         if (x < 64) {
53             evt.agentSlot = 2;
54         } else {
55             evt.agentSlot = 3;
56         }
57     }
58     else
59     {
60         scanCoordsForIPA(x,y, evt);
61     }
62 
63     return evt.eventType != SelectorEvent::kNone;
64 }
65 
scanCoordsForIPA(int x,int y,SelectorEvent & evt)66 void AgentSelectorRenderer::scanCoordsForIPA(int x, int y, SelectorEvent & evt)
67 {
68     IPAStim::IPAType types[] = {IPAStim::Adrenaline, IPAStim::Perception, IPAStim::Intelligence};
69     // For each agent
70     for(size_t a = 0; a < AgentManager::kMaxSlot; ++a)
71     {
72         int barLeft = getIpaBarLeftForAgent(a);
73         if(x >= barLeft && x <= barLeft + kIpaBarWidth)
74         {
75             // For each type of IPA
76             for (int i = 0; i < 3; ++i) {
77                 int barTop = getIpaBarTop(a, types[i]);
78                 if( y >= barTop && y <= barTop + kIpaBarHeight) {
79                     evt.eventType = SelectorEvent::kSelectIpa;
80                     evt.agentSlot = a;
81                     evt.IpaType = types[i];
82                     evt.percentage = getPercentage(barLeft, x);
83                     return;
84                 }
85             }
86         }
87     }
88 }
89 
90 /*!
91  * Draws all the elements
92  * for one bar
93  */
drawIPABar(int agent,IPAStim * stim)94 void AgentSelectorRenderer::drawIPABar(int agent, IPAStim *stim)
95 {
96     // Convert those percentages to pixels
97     int amount_x = (float)kIpaBarWidth * ((float)stim->getAmount()/100.0);
98     int effect_x = (float)kIpaBarWidth * ((float)stim->getEffect()/100.0);
99     int dependency_x = (float)kIpaBarWidth * ((float)stim->getDependency()/100.0);
100 
101     IPAStim::IPAType type = stim->getType();
102 
103     // Draw a bar between the current level and the dependency marker
104     // x needs to be leftmost...
105     int left, width;
106     boxify(left, width, amount_x, dependency_x);
107     if(width > 0) {
108         g_Screen.drawRect(getIpaBarLeftForAgent(agent) + left,
109                           getIpaBarTop(agent, type),
110                           width, kIpaBarHeight, colourForIpaType(type));
111     }
112 
113     // NB: this bar stops rendering when it's neck-a-neck with 'amount'
114     if(amount_x != effect_x)
115     {
116         boxify(left, width, effect_x, dependency_x);
117         if(width > 0) {
118             g_Screen.drawRect(getIpaBarLeftForAgent(agent) + left,
119                               getIpaBarTop(agent, type),
120                               width, kIpaBarHeight, dim_colour(type));
121         }
122     }
123 
124     // Draw a vertical white line to mark the dependency level
125     g_Screen.drawVLine(getIpaBarLeftForAgent(agent) + dependency_x,
126                       getIpaBarTop(agent, type), kIpaBarHeight, 12);
127 }
128 
129 /*!
130  * Draw the complete selector for an agent.
131  * \param agentSlot
132  * \param pAgent
133  * \param isSelected
134  */
drawSelectorForAgent(size_t agentSlot,PedInstance * pAgent,bool isSelected)135 void AgentSelectorRenderer::drawSelectorForAgent(size_t agentSlot,
136     PedInstance *pAgent, bool isSelected)
137 {
138     // parity check
139     int topX = (agentSlot & 0x01) * 64;
140     // 2,3 should be drawn at (46 + 44 + 10)
141     int topY = (agentSlot >> 1) * (46 + 44 + 10);
142     int spriteSelected = 1772 + agentSlot;
143     int springUnselected = 1748 + (agentSlot > 1 ? agentSlot + 2 : agentSlot);
144 
145     // Draw the background of selector
146     g_App.gameSprites().sprite(isSelected ? spriteSelected : springUnselected)->draw(
147             topX, topY, 0);
148     g_App.gameSprites().sprite(isSelected ? 1778 : 1754)->draw(
149             topX, topY + 46, 0);
150 
151     if (pAgent) {
152         // draw health bar
153         int ydiff = 36 * pAgent->health() / pAgent->startHealth();
154         g_Screen.drawRect(topX + 51,
155             topY + 6 + 36 - ydiff, 7, ydiff, 12);
156 
157         //draw animation within selectors
158         pAgent->drawSelectorAnim(topX + 32, topY + 38);
159 
160         // draw IPA, for alive only agents
161         if (pAgent->isAlive()) {
162             drawIPABar(agentSlot, pAgent->adrenaline_);
163             drawIPABar(agentSlot, pAgent->perception_);
164             drawIPABar(agentSlot, pAgent->intelligence_);
165         }
166     }
167 }
168 
169 /*!
170  * Draw all elements for the agent selectors.
171  */
render(SquadSelection & selection,Squad * pSquad)172 void AgentSelectorRenderer::render(SquadSelection & selection, Squad * pSquad) {
173     for (size_t a = 0; a < AgentManager::kMaxSlot; a++) {
174         PedInstance * pAgent = pSquad->member(a);
175         drawSelectorForAgent(a, pAgent, selection.isAgentSelected(a));
176     }
177 }
178