2 @Copyright Looking Glass Studios, Inc.
3 1996,1997,1998,1999,2000 Unpublished Work.
6 ///////////////////////////////////////////////////////////////////////////////
7 // $Header: r:/t2repos/thief2/src/ai/aicbrsht.cpp,v 1.9 2000/02/03 16:36:39 bfarquha Exp $
33 // Must be last header
36 ////////////////////////////////////////
38 const float kAIRS_HeadingTolerance
= 0.25;
40 ////////////////////////////////////////
42 void cAIRangedShoot::Reset(void)
44 projectile
= OBJ_NULL
;
45 proj_link_data
= NULL
;
48 ////////////////////////////////////////
50 int cAIRangedShoot::SuggestApplicability(void)
52 // wsf: timer causing problems. When we're ready to fire (new ranged combat), the question
53 // is asked if this mode (long range shoot) wants to continue. It responds 'no' because the
54 // timer hasn't kicked off yet (still have .7 seconds to go for frogmen - the timer stars when action is
55 // selected), which makes this mode come to a premature end, and be replaced with frustration.
57 // if (m_pOwner->m_FiringDelay.Expired() && GetCurrentLocation()->GetLOF())
59 if (GetCurrentLocation()->GetLOF())
60 return g_AIRangedCombatModeWeights
[AIGetRangedShoot(GetID())->m_rangeApplicability
[GetRangeClass()]];
65 ////////////////////////////////////////
67 BOOL
cAIRangedShoot::CheckContinuation(void)
69 sAIRangedShootParams
*pParams
= AIGetRangedShoot(GetID());
71 if ((pParams
->m_confirmRange
) && (pParams
->m_rangeApplicability
[GetRangeClass()]==kAIRC_AppNone
))
73 if ((pParams
->m_confirmLOF
) && !m_pOwner
->GetCurrentLocation()->TestLOF())
78 ////////////////////////////////////////
80 int cAIRangedShoot::SuggestInterrupt(void)
82 // @TODO: interrupt should look at property & how far off our facing is
83 return SuggestApplicability();
86 ////////////////////////////////////////
88 BOOL
cAIRangedShoot::CheckPreconditions(void)
90 m_pOwner
->SelectProjectile(&projectile
, &proj_link_data
, &targeting_location
);
91 return (projectile
!= OBJ_NULL
);
94 ////////////////////////////////////////
96 cAIAction
* cAIRangedShoot::SuggestAction(void)
98 cAIAction
* pAction
= NULL
;
100 Assert_(projectile
!= OBJ_NULL
);
101 AIWatch1(Ranged
, GetID(), "Launching projectile: %d", projectile
);
103 // Tell all the other projectiles that they weren't selected
104 m_pOwner
->RefreshProjectilesProj(projectile
);
106 // Pull one out of the inventory
107 AutoAppIPtr(ContainSys
);
108 AutoAppIPtr_(ObjectSystem
, pObjSys
);
109 ObjID firing_projectile
;
111 // We want to delete the object if we run out of ammo, but we also
112 // want its link around until we're done creating the action, so
113 // we defer deletions until then.
117 firing_projectile
= pObjSys
->Create(projectile
, kObjectConcrete
);
119 // Remove its physics and make it invisible
120 g_pPhysTypeProp
->Delete(firing_projectile
);
121 ObjSetHasRefs(firing_projectile
, FALSE
);
123 // Decrement stack count
127 if (proj_link_data
->burst_count
> 0)
128 burst_count
= proj_link_data
->burst_count
;
132 if (proj_link_data
->ammo
> 0)
134 IIntProperty
*pStackCountProp
= pContainSys
->StackCountProp();
137 if (pStackCountProp
->Get(projectile
, &count
))
139 if (count
< burst_count
)
142 fire_count
= burst_count
;
147 pStackCountProp
->Set(projectile
, count
);
149 pObjSys
->Destroy(projectile
);
152 CriticalMsg("Selected projectile w/o ammo!");
155 fire_count
= burst_count
;
157 // @TODO: handle specifying launch point
159 cAIAttackRangedAction
*pAttackAction
= new cAIAttackRangedAction(m_pOwner
);
161 if (m_pOwner
->m_ReactShootTimer
.Expired())
163 if (GetInternalAI()->AccessSoundEnactor())
164 GetInternalAI()->AccessSoundEnactor()->RequestConcept(kAISC_ReactShoot
);
165 m_pOwner
->m_ReactShootTimer
.Reset();
168 if ((proj_link_data
->targeting_method
== kTM_StraightLine
) ||
169 (proj_link_data
->targeting_method
== kTM_Arcing
))
171 if (GetCurrentLocation()->GetTargetSubModel()>=0)
172 pAttackAction
->Set(GetTargetInfo()->id
, GetCurrentLocation()->GetTargetSubModel(), firing_projectile
, proj_link_data
->leads_target
,
173 proj_link_data
->accuracy
, fire_count
, proj_link_data
->launch_joint
);
175 pAttackAction
->Set(GetTargetInfo()->id
, firing_projectile
, proj_link_data
->leads_target
,
176 proj_link_data
->accuracy
, fire_count
, proj_link_data
->launch_joint
);
180 pAttackAction
->Set(targeting_location
, firing_projectile
, proj_link_data
->accuracy
,
181 fire_count
, proj_link_data
->launch_joint
);
183 // Tell the action how fast to rotate and how close is close enough (in heading)
184 pAttackAction
->SetRotationParams(AIGetRangedShoot(GetID())->m_rotationSpeed
, kAIRS_HeadingTolerance
);
189 float randVar
= 1.0 + (AIRandom(0, kRandVar
* 2) - kRandVar
) / 100.0;
190 m_pOwner
->m_FiringDelay
.Set((eAITimerPeriod
)(unsigned)(GetRangedCombatProp()->firing_delay
* 1000 * randVar
));
192 return pAttackAction
;