Torque3D Documentation / _generateds / afxEA_Projectile.cpp

afxEA_Projectile.cpp

Engine/source/afx/ea/afxEA_Projectile.cpp

More...

Classes:

Detailed Description

  1
  2
  3//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
  4// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
  5// Copyright (C) 2015 Faust Logic, Inc.
  6//
  7// Permission is hereby granted, free of charge, to any person obtaining a copy
  8// of this software and associated documentation files (the "Software"), to
  9// deal in the Software without restriction, including without limitation the
 10// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 11// sell copies of the Software, and to permit persons to whom the Software is
 12// furnished to do so, subject to the following conditions:
 13//
 14// The above copyright notice and this permission notice shall be included in
 15// all copies or substantial portions of the Software.
 16//
 17// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 18// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 19// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 20// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 21// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 22// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 23// IN THE SOFTWARE.
 24//
 25//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
 26
 27#include <typeinfo>
 28#include "afx/arcaneFX.h"
 29
 30#include "lighting/lightInfo.h"
 31#include "T3D/projectile.h"
 32
 33#include "afx/afxEffectDefs.h"
 34#include "afx/afxEffectWrapper.h"
 35#include "afx/afxChoreographer.h"
 36#include "afx/ce/afxProjectile.h"
 37
 38//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
 39// afxEA_Projectile 
 40
 41class afxEA_Projectile : public afxEffectWrapper
 42{
 43  typedef afxEffectWrapper Parent;
 44
 45  ProjectileData*     projectile_data;
 46  afxProjectileData*  afx_projectile_data;
 47  afxProjectile*      projectile;
 48  bool                launched;
 49  bool                impacted;
 50  bool                projectile_done;
 51  afxConstraint*      launch_cons;
 52  Point3F             launch_dir_bias;
 53
 54  void                do_runtime_substitutions();
 55
 56public:
 57  /*C*/               afxEA_Projectile();
 58  /*D*/               ~afxEA_Projectile();
 59
 60  virtual bool        isDone();
 61
 62  virtual void        ea_set_datablock(SimDataBlock*);
 63  virtual bool        ea_start();
 64  virtual bool        ea_update(F32 dt);
 65  virtual void        ea_finish(bool was_stopped);
 66
 67  virtual void        onDeleteNotify(SimObject*);
 68};
 69
 70//~~~~~~~~~~~~~~~~~~~~//
 71
 72afxEA_Projectile::afxEA_Projectile()
 73{
 74  projectile_data = 0;
 75  afx_projectile_data = 0;
 76  projectile = 0;
 77  launched = false;
 78  impacted = false;
 79  projectile_done = false;
 80  launch_cons = 0;
 81  launch_dir_bias.zero();
 82}
 83
 84afxEA_Projectile::~afxEA_Projectile()
 85{
 86  if (projectile)
 87    clearNotify(projectile);
 88  //if (projectile_data && projectile_data->isTempClone())
 89  //  delete projectile_data;
 90  projectile_data = 0;
 91  afx_projectile_data = 0;
 92}
 93
 94bool afxEA_Projectile::isDone()
 95{
 96  return (mDatablock->use_as_cons_obj || mDatablock->use_ghost_as_cons_obj) ? projectile_done : impacted;
 97}
 98
 99void afxEA_Projectile::ea_set_datablock(SimDataBlock* db)
100{
101  projectile_data = dynamic_cast<ProjectileData*>(db);
102  afx_projectile_data =  dynamic_cast<afxProjectileData*>(projectile_data);
103}
104
105bool afxEA_Projectile::ea_start()
106{
107  if (!projectile_data)
108  {
109    Con::errorf("afxEA_Projectile::ea_start() -- missing or incompatible datablock.");
110    return false;
111  }
112
113  do_runtime_substitutions();
114
115  if (!afx_projectile_data)
116  {
117    projectile = new afxProjectile();
118  }
119  else
120  {
121    if (mDatablock->use_ghost_as_cons_obj && mDatablock->effect_name != ST_NULLSTRING)
122      projectile = new afxProjectile(afx_projectile_data->networking, mChoreographer->getChoreographerId(), mDatablock->effect_name);
123    else
124      projectile = new afxProjectile(afx_projectile_data->networking, 0, ST_NULLSTRING);
125    projectile->ignoreSourceTimeout = afx_projectile_data->ignore_src_timeout;
126    if (afx_projectile_data->override_collision_masks)
127    {
128      projectile->dynamicCollisionMask = afx_projectile_data->dynamicCollisionMask;
129      projectile->staticCollisionMask = afx_projectile_data->staticCollisionMask;
130    }
131    afxConstraintID launch_pos_id = mCons_mgr->getConstraintId(afx_projectile_data->launch_pos_def);
132    launch_cons = mCons_mgr->getConstraint(launch_pos_id);
133    launch_dir_bias = afx_projectile_data->launch_dir_bias;
134  }
135
136  projectile->onNewDataBlock(projectile_data, false);
137
138  return true;
139}
140
141bool afxEA_Projectile::ea_update(F32 dt)
142{
143  if (!launched && projectile)
144  {
145    if (mIn_scope)
146    {
147      afxConstraint* pos_cons = getPosConstraint();
148      ShapeBase* src_obj = (pos_cons) ? (dynamic_cast<ShapeBase*>(pos_cons->getSceneObject())) : 0;
149
150      F32 muzzle_vel = projectile_data->muzzleVelocity;
151
152      Point3F dir_vec;
153      if (afx_projectile_data)
154      {
155        switch (afx_projectile_data->launch_dir_method)
156        {
157        case afxProjectileData::OrientConstraint:
158          dir_vec.set(0,0,1); 
159          mUpdated_xfm.mulV(dir_vec);
160          break;
161        case afxProjectileData::LaunchDirField:
162          dir_vec.set(0,0,1); 
163          break;
164        case afxProjectileData::TowardPos2Constraint:
165        default:
166          dir_vec = mUpdated_aim - mUpdated_pos;
167          break;
168        }
169      }
170      else
171        dir_vec = mUpdated_aim - mUpdated_pos;
172
173      dir_vec.normalizeSafe();
174      if (!launch_dir_bias.isZero())
175      {
176        dir_vec += launch_dir_bias;
177        dir_vec.normalizeSafe();
178      }
179      dir_vec *= muzzle_vel;
180
181      Point3F launch_pos;
182      if (launch_cons && launch_cons->getPosition(launch_pos))
183      {
184        ShapeBase* launch_obj = (launch_cons) ? (dynamic_cast<ShapeBase*>(launch_cons->getSceneObject())) : 0;
185        projectile->init(launch_pos, dir_vec, (launch_obj) ? launch_obj : src_obj);
186      }
187      else
188        projectile->init(mUpdated_pos, dir_vec, src_obj);
189
190      if (!projectile->registerObject())
191      {
192        delete projectile;
193        projectile = 0;
194        Con::errorf("afxEA_Projectile::ea_update() -- effect failed to register.");
195        return false;
196      }
197
198      deleteNotify(projectile);
199
200      if (projectile)
201        projectile->setDataField(StringTable->insert("afxOwner"), 0, mChoreographer->getIdString());
202
203    }
204    launched = true;
205  }
206
207  if (launched && projectile)
208  {
209    if (mIn_scope)
210    {
211      mUpdated_xfm = projectile->getRenderTransform();
212     mUpdated_xfm.getColumn(3, &mUpdated_pos);
213    }
214  }
215
216  return true;
217}
218
219void afxEA_Projectile::ea_finish(bool was_stopped)
220{
221  if (projectile)
222  {
223    clearNotify(projectile);
224    projectile = 0;
225  }
226  launched = false;
227  impacted = false;
228}
229
230void afxEA_Projectile::onDeleteNotify(SimObject* obj)
231{
232  // projectile deleted?
233  Projectile* del_projectile = dynamic_cast<Projectile*>(obj);
234  if (del_projectile == projectile)
235  {
236    projectile = NULL;
237    projectile_done = true;
238  }
239}
240
241void afxEA_Projectile::do_runtime_substitutions()
242{
243  // only clone the datablock if there are substitutions
244  if (projectile_data->getSubstitutionCount() > 0)
245  {
246    if (typeid(afxProjectileData) == typeid(*projectile_data))
247    {
248      afxProjectileData* orig_db = (afxProjectileData*)projectile_data;
249      afx_projectile_data = new afxProjectileData(*orig_db, true);
250      projectile_data = afx_projectile_data;
251      orig_db->performSubstitutions(projectile_data, mChoreographer, mGroup_index);
252    }
253    else
254    {
255      // clone the datablock and perform substitutions
256      ProjectileData* orig_db = projectile_data;
257      afx_projectile_data = 0;
258      projectile_data = new ProjectileData(*orig_db, true);
259      orig_db->performSubstitutions(projectile_data, mChoreographer, mGroup_index);
260    }
261  }
262}
263
264
265//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
266
267class afxEA_ProjectileDesc : public afxEffectAdapterDesc, public afxEffectDefs 
268{
269  static afxEA_ProjectileDesc desc;
270
271public:
272  virtual bool  testEffectType(const SimDataBlock*) const;
273  virtual bool  requiresStop(const afxEffectWrapperData*, const afxEffectTimingData&) const;
274  virtual bool  runsOnServer(const afxEffectWrapperData*) const;
275  virtual bool  runsOnClient(const afxEffectWrapperData*) const;
276
277  virtual afxEffectWrapper* create() const { return new afxEA_Projectile; }
278};
279
280afxEA_ProjectileDesc afxEA_ProjectileDesc::desc;
281
282bool afxEA_ProjectileDesc::testEffectType(const SimDataBlock* db) const
283{
284  if (typeid(ProjectileData) == typeid(*db))
285    return true;
286  if (typeid(afxProjectileData) == typeid(*db))
287    return true;
288  return false;
289}
290
291bool afxEA_ProjectileDesc::requiresStop(const afxEffectWrapperData* ew, const afxEffectTimingData& timing) const
292{
293  return ((ew->use_as_cons_obj || ew->use_ghost_as_cons_obj) && timing.lifetime < 0);
294}
295
296bool afxEA_ProjectileDesc::runsOnServer(const afxEffectWrapperData* ew) const
297{
298  afxProjectileData* afx_projectile_data = dynamic_cast<afxProjectileData*>(ew->effect_data);
299  if (!afx_projectile_data)
300    return true;
301
302  U8 networking = ((const afxProjectileData*)ew->effect_data)->networking;
303  return ((networking & CLIENT_ONLY) == 0);
304}
305
306bool afxEA_ProjectileDesc::runsOnClient(const afxEffectWrapperData* ew) const
307{ 
308  afxProjectileData* afx_projectile_data = dynamic_cast<afxProjectileData*>(ew->effect_data);
309  if (!afx_projectile_data)
310    return false;
311
312  U8 networking = ((const afxProjectileData*)ew->effect_data)->networking;
313  return ((networking & CLIENT_ONLY) != 0);
314}
315
316//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
317