JNR
laMonster.cpp
1 /*
2 
3 Jump'n'Run Engine
4 http://www.atanaslaskov.com/jnr/
5 
6 BSD LICENSE
7 Copyright (c) 2007-2013, Atanas Laskov
8 All rights reserved.
9 
10 Redistribution and use in source and binary forms, with or without
11 modification, are permitted provided that the following conditions are met:
12 1. Redistributions of source code must retain the above copyright notice,
13 this list of conditions and the following disclaimer.
14 2. Redistributions in binary form must reproduce the above copyright notice,
15 this list of conditions and the following disclaimer in the documentation
16 and/or other materials provided with the distribution.
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 DISCLAIMED. IN NO EVENT SHALL ATANAS LASKOV BE LIABLE FOR ANY
21 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 */
29 //
30 // FILE: laMonster.cpp
31 //
32 // Copyright (C) 2007-2013 Atanas Laskov, <latanas@gmail.com>
33 //
34 #include "stdafx.h"
35 #include "Core-Level-JR.h"
36 
37 laTexture laMonster::_texInRange;
38 laTexture laMonster::_texNPCInRange;
39 
40 // Constructor
41 //
42 laMonster::laMonster(void):
44 {
45  _dDeltaL = _dDeltaR = M_UNIT;
46 
47  // Setup attack indicator
48  //
49  _IndicatorAttack.setColor(laColor(200,200,200));
50  _IndicatorAttack.setSize(M_HPBAR_W, M_HPBAR_H/2);
51  _IndicatorAttack.setMaxValue( 1 );
52 
53  // Agressive by default
54  _bAgressiveMode = M_TRUE;
55  enableBattleGUI(M_TRUE);
56  enableNPCGUI(M_FALSE);
57 }
58 
59 laMonster::~laMonster(void) {
60 }
61 
62 // Respawn monster
63 //
64 void laMonster::respawn()
65 {
66  laFightingCreature::respawn();
67 
68  // Extract creature properties
69  //_pSheet->load( getObject()->getChild("rpg-sheet") );
70 }
71 
72 // Load from level file
73 //
74 void laMonster::load(class laFileParser *fp)
75 {
76  ERRORLEVEL_BEGIN;
77  laFightingCreature::load(fp);
78 
79  // Load territory range
80  //
81  fp->readDouble(&_dDeltaL);
82  fp->readDouble(&_dDeltaR);
83 
84  _dDeltaL *= M_UNIT;
85  _dDeltaR *= M_UNIT;
86 
87  // Extract creature properties
88  //_pSheet->load( getObject()->getChild("rpg-sheet") );
89 
90  // Setup GUI
91  //
92  _IndicatorHP.setColor(laColor(200,0,0));
93  _IndicatorHP.setSize(M_HPBAR_W, M_HPBAR_H);
94  _IndicatorHP.setMaxValue( ((rpgSheet_Fighter*)_pSheet)->properties()->nHP_Max );
95 
96  if(_texInRange.id()==NULL)
97  _texInRange.load("gui\\within_range_marker.png", M_TEX_TMAP);
98 
99  if(_texNPCInRange.id()==NULL)
100  _texNPCInRange.load("gui\\within_range_marker_NPC.gif"/*, M_TEX_TMAP*/);
101 
102  // Disable trail FX for monsters
103  _fxTrail.enable(M_FALSE);
104 
105  ERRORLEVEL_END;
106 }
107 
108 // Execute AI: update percepts & call handlers
109 //
110 void laMonster::_execute_ai(laTimer &t)
111 {
112  ERRORLEVEL_BEGIN;
113  laPlayer *pPlayer = (laPlayer*)( getLevelObject()->getPlayer() );
114  laLine2 ln(pPlayer->getPosition(), _ptPivot);
115  double dPlayer = ln.lenght();
116 
117  if( (M_ABS(pPlayer->getMonsterDistance() /*- M_PLAYER_ATTACK_RANGE*/) > dPlayer) && isAlive() )
118  {
119  if( _ptPivot.x() > pPlayer->getPivot()->x() ) pPlayer->setMonsterDistance(dPlayer);
120  else pPlayer->setMonsterDistance( -1*dPlayer );
121  }
122 
123  // Perceive player actions only if on the same level along Y
124  //
125  if( M_ABS( pPlayer->getPosition().y() - _ptPivot.y() ) < M_UNIT*3 )
126  {
127  // Check if the player is in contact with the monster
128  //
129  if( pPlayer->boundingRect().intersecting(boundingRect()) )
130  {
131  _ai.perceive(P__PLAYER_TOUCHED);
132  }
133 
134  // Check if the player is commencing an attack
135  //
136  if( _isInRange(pPlayer, this) && pPlayer->attackIsCharged() &&
137  (( (pPlayer->getFaceDirection()<0) && (pPlayer->getPosition().x()>_ptPivot.x()) )
138  || ( (pPlayer->getFaceDirection()>0) && (pPlayer->getPosition().x()<_ptPivot.x()) )) )
139  {
140  _ai.perceive(P__PLAYER_ATTACKS);
141  }
142 
143  // Check if the player is in our attack range
144  //
145  // NOTE: Calculating the attack range only along X;
146  // this works better for flying mobs
147  //
148  if( _isInRange(this, pPlayer) )
149  {
150  _ai.perceive(P__PLAYER_IN_RANGE);
151  _ai.perceive(P__PLAYER_IN_TERRITORY);
152  }
153  else
154  {
155  //Check if the player is inside the bounds of our teritory
156  //
157  if( (pPlayer->getPosition().x() >= (_ptOriginPos.x() - _dDeltaL)) &&
158  (pPlayer->getPosition().x() <= (_ptOriginPos.x() + _dDeltaR)) )
159  {
160  _ai.perceive(P__PLAYER_IN_TERRITORY);
161  }
162  }
163  }
164 
165  //Default
166  laFightingCreature::_execute_ai(t);
167 
168  ERRORLEVEL_END;
169 }
170 
171 M_BOOL laMonster::_isInRange(laFightingCreature* pAgressor, laFightingCreature* pTarget)
172 {
173  // NOTE: Calculating the attack range only along X; works better for flying mobs
174  // (dPlayer < M_MATTACK_RANGE)
175 
176  rpgAttack atk = pAgressor->selectedAttack();
177 
178  if( M_ABS(pAgressor->getPosition().x() - pTarget->getPosition().x()) > atk.dRange ) return M_FALSE;
179  if( M_ABS(pAgressor->getPosition().y() - pTarget->getPosition().y()) > 1.5 * M_UNIT ) return M_FALSE;
180 
181  return M_TRUE;
182 }
183 
184 // Draw FX
185 //
186 void laMonster::_drawFx_positioned(laRenderer *r)
187 {
188  // Draw monster-specific GUI (in 3D)
189  //
190  if(isAlive())
191  {
192  laPoint3 ptCamAng = r->getCameraAngles();
193 
194  r->transPush();
195  r->transRotate(-1*ptCamAng.y(), laPoint3(0,1,0)); //< Make camera facing - compensate for camera angle
196  r->modeDepthBuffer(M_FALSE);
197 
198  if(_bEnable_Battle_GUI) _draw_battle_gui(r);
199  if(_bEnable_NPC_GUI) _draw_npc_gui(r);
200 
201  r->modeDepthBuffer(M_TRUE);
202  r->transPop();
203  }
204 
205  laFightingCreature::_drawFx_positioned(r);
206 }
207 
208 // Draw 2D interface
209 //
210 void laMonster::drawInterface(laRenderer *r, laPoint3 ptBasePos) {
211  laFightingCreature::drawInterface(r, ptBasePos);
212 }
213 
214 // Draw battle GUI
215 //
216 void laMonster::_draw_battle_gui(laRenderer *r)
217 {
218  // Battle icon
219  //
220  laPoint3 pos(M_BATTLEICON_SZ/2, _ptPivot.size.y() + M_HPBAR_HOVER + M_HPBAR_H + M_BATTLEICON_SZ*1.1+ 0.24*M_UNIT);
221  pos *= -1;
222 
223  r->vquadsMakeXYRect(0, pos, laPoint3(M_BATTLEICON_SZ, M_BATTLEICON_SZ), laPoint2(), laPoint2(1,1));
224  _texInRange.use();
225  r->styleSet(laColor(255));
226  r->vquadsDrawSingle();
227 
228  // HP Bar
229  //
230  pos = laPoint3(M_HPBAR_W/2, _ptPivot.size.y() + M_HPBAR_HOVER + M_HPBAR_H + 0.24*M_UNIT);
231  pos *= -1;
232 
233  r->modeTexture(M_FALSE);
234  _IndicatorHP.value( ((rpgSheet_Fighter*)_pSheet)->properties()->nHP );
235  _IndicatorHP.draw(r, pos);
236 
237  // Attack charge bar
238  //
239  if( _ttAttackCharge.isEnabled() || _ttAttack.isEnabled() )
240  {
241  pos.y( pos.y() + M_UNIT/6.0);
242  _IndicatorAttack.value( 1 - _ttAttackCharge.reminder() );
243  _IndicatorAttack.draw(r, pos);
244  }
245 }
246 
247 // Draw NPC GUI
248 //
249 void laMonster::_draw_npc_gui(laRenderer *r)
250 {
251  laPoint3 pos(M_BATTLEICON_SZ/2, _ptPivot.size.y() + M_HPBAR_HOVER + M_HPBAR_H + M_BATTLEICON_SZ*1.1+ 0.24*M_UNIT);
252  pos *= -1;
253 
254  r->vquadsMakeXYRect(0, pos, laPoint3(M_BATTLEICON_SZ, M_BATTLEICON_SZ), laPoint2(), laPoint2(1,1));
255  _texNPCInRange.use();
256  r->styleSet(laColor(255));
257  r->vquadsDrawSingle();
258 }
virtual void modeTexture(M_BOOL bOn)=0
Enable/disable texturing.
Playable Character.
Definition: laPlayer.h:46
#define M_UNIT
Unit of 1 meter.
virtual void vquadsDrawSingle(laPoint2 *ar_uv=NULL)=0
Draw a single VQ (Note this is slower than drawing an array of VQ and should be avoided) ...
2D Point
Definition: laPoint_novec.h:41
void vquadsMakeXYRect(unsigned nIndex, const laPoint3 &pos, const laPoint3 &sz, const laPoint2 &uv, const laPoint2 &uv_sz)
Makes a quad aligned to the XY plane; (handy for GUI rendering )
Definition: laRenderer.h:328
2D line segment
Definition: laLine2.h:40
2D Texture
Definition: laTexture.h:45
#define M_ABS(a)
Return abs(a)
virtual void modeDepthBuffer(M_BOOL bOn)=0
Enable/disable depth buffer.
Virtual interface for the Engine graphics renderer.
Definition: laRenderer.h:98
#define M_TEX_TMAP
Transparent texture with an alpha channel.
Attack RPG Properties.
Definition: rpgAttack.h:55
File Parser.
Definition: laFileParser.h:41