Planeshift
|
00001 /* 00002 * npcbehave.h 00003 * 00004 * Copyright (C) 2003 Atomic Blue ([email protected], http://www.atomicblue.org) 00005 * 00006 * 00007 * This program is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU General Public License 00009 * as published by the Free Software Foundation (version 2 of the License) 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software 00016 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00017 * 00018 */ 00019 00020 /* This file holds definitions for ALL global variables in the planeshift 00021 * server, normally you should move global variables into the psServer class 00022 */ 00023 #ifndef __NPCBEHAVE_H__ 00024 #define __NPCBEHAVE_H__ 00025 //============================================================================= 00026 // Crystal Space Includes 00027 //============================================================================= 00028 #include <csgeom/matrix3.h> 00029 #include <csutil/array.h> 00030 #include <iutil/document.h> 00031 00032 struct iSector; 00033 00034 //============================================================================= 00035 // Library Includes 00036 //============================================================================= 00037 #include "util/eventmanager.h" 00038 #include "util/gameevent.h" 00039 #include "util/consoleout.h" 00040 #include "util/pspath.h" 00041 00042 //============================================================================= 00043 // Local Includes 00044 //============================================================================= 00045 #include "perceptions.h" 00046 #include "walkpoly.h" 00047 #include "npcoperations.h" 00048 00053 class ScriptOperation; 00054 class Perception; 00055 class Reaction; 00056 class Behavior; 00057 class NPC; 00058 class EventManager; 00059 class BehaviorSet; 00060 class Waypoint; 00061 00069 class BehaviorSet 00070 { 00071 protected: 00072 csPDelArray<Behavior> behaviors; 00073 Behavior* active; 00074 00075 public: 00078 BehaviorSet(); 00079 00090 bool Add(Behavior* behavior); 00091 00099 Behavior* Find(const char* name); 00100 00109 void DeepCopy(BehaviorSet &other); 00110 00119 void ClearState(NPC* npc); 00120 00129 void UpdateNeeds(float delta, NPC* npc); 00130 00135 Behavior* Schedule(NPC* npc); 00136 00145 void Advance(csTicks delta, NPC* npc); 00146 00154 void Execute(NPC* npc, bool forceRunScript); 00155 00163 void Interrupt(NPC* npc); 00164 00167 Behavior* GetCurrentBehavior() 00168 { 00169 return active; 00170 } 00171 00176 void DumpBehaviorList(csString &output, NPC* npc); 00177 00182 csString InfoBehaviors(NPC* npc); 00183 00186 float GetHighestNeed(NPC* npc); 00187 00188 }; 00189 00190 00197 class NPCType 00198 { 00199 protected: 00200 NPC* npc; 00201 csString name; 00202 csPDelArray<Reaction> reactions; 00203 BehaviorSet behaviors; 00204 float ang_vel; 00205 00206 00207 float vel; 00208 00209 00210 ScriptOperation::VelSource velSource; 00211 00212 csString collisionPerception; 00213 csString outOfBoundsPerception; 00214 csString inBoundsPerception; 00215 csString fallingPerception; 00216 00217 public: 00218 NPCType(); 00219 NPCType(NPCType &other, NPC* npc); 00220 00221 ~NPCType(); 00222 void DeepCopy(NPCType &other); 00223 void ClearState(NPC* npc); 00224 00225 bool Load(iDocumentNode* node); 00226 bool Load(iResultRow &node); 00227 const char* GetName() 00228 { 00229 return name.GetDataSafe(); 00230 } 00231 00239 Behavior* Find(const char* name) 00240 { 00241 return behaviors.Find(name); 00242 } 00243 00244 void Advance(csTicks delta, NPC* npc); 00245 void Interrupt(NPC* npc); 00246 void FirePerception(NPC* npc,Perception* pcpt); 00247 00248 void DumpBehaviorList(csString &output, NPC* npc) 00249 { 00250 behaviors.DumpBehaviorList(output, npc); 00251 } 00252 csString InfoBehaviors(NPC* npc) 00253 { 00254 return behaviors.InfoBehaviors(npc); 00255 } 00256 00261 csString InfoReactions(NPC* npc); 00262 00267 void DumpReactionList(csString &output, NPC* npc); 00268 00269 Behavior* GetCurrentBehavior() 00270 { 00271 return behaviors.GetCurrentBehavior(); 00272 } 00273 00278 float GetHighestNeed(NPC* npc); 00279 00284 float GetAngularVelocity(NPC* npc); 00285 00290 float GetVelocity(NPC* npc); 00291 00294 void SetVelSource(ScriptOperation::VelSource velSource, float vel); 00295 00298 const csString &GetCollisionPerception() const; 00299 00304 const csString &GetOutOfBoundsPerception() const; 00305 00310 const csString &GetInBoundsPerception() const; 00311 00314 const csString &GetFallingPerception() const; 00315 00316 00317 private: 00322 void AddReaction(Reaction* reaction); 00323 00328 void InsertReaction(Reaction* reaction); 00329 }; 00330 00331 00340 class Behavior 00341 { 00342 public: 00343 // Used to indicate the result of the RunScript operation of a behavior. 00344 enum BehaviorResult 00345 { 00346 BEHAVIOR_NOT_COMPLETED, 00347 BEHAVIOR_COMPLETED, 00348 BEHAVIOR_WILL_COMPLETE_LATER, 00349 BEHAVIOR_FAILED 00350 }; 00351 protected: 00352 csString name; 00353 00354 csPDelArray<ScriptOperation> sequence; 00355 size_t current_step; 00356 size_t stepCount; 00357 bool loop; 00358 bool isActive; 00359 bool is_applicable_when_dead; 00360 float need_decay_rate; 00361 float need_growth_rate; 00362 float completion_decay; 00363 float init_need; 00364 bool resume_after_interrupt; 00365 csString interruptPerception; 00366 00367 float current_need; 00368 float new_need; 00369 00370 bool interrupted; 00371 00372 bool minLimitValid; 00373 float minLimit; 00374 bool maxLimitValid; 00375 float maxLimit; 00376 csString failurePerception; 00377 00378 public: 00379 00380 Behavior(); 00381 Behavior(const char* n); 00382 Behavior(Behavior &other); 00383 00384 virtual ~Behavior() { }; 00385 00386 const char* GetName() 00387 { 00388 return name; 00389 } 00390 00391 void DeepCopy(Behavior &other); 00392 bool Load(iDocumentNode* node); 00393 00394 bool LoadScript(iDocumentNode* node,bool top_level=true); 00395 00396 void UpdateNeed(float delta, NPC* npc); 00397 BehaviorResult Advance(float delta, NPC* npc); 00398 float CurrentNeed() 00399 { 00400 return current_need; 00401 } 00402 float NewNeed() 00403 { 00404 return new_need; 00405 } 00406 00416 void CommitAdvance(); 00417 00428 void ApplyNeedDelta(NPC* npc, float deltaDesire); 00429 00430 00442 void ApplyNeedAbsolute(NPC* npc, float absoluteDesire); 00443 00444 void SetIsActive(bool flag) 00445 { 00446 isActive = flag; 00447 } 00448 00455 bool IsActive() 00456 { 00457 return isActive; 00458 } 00459 00460 void SetCurrentStep(int step); 00461 size_t GetCurrentStep() 00462 { 00463 return current_step; 00464 } 00465 size_t GetLastStep() 00466 { 00467 return sequence.GetSize(); 00468 } 00469 void ResetNeed() 00470 { 00471 current_need = new_need = init_need; 00472 } 00473 00474 bool ApplicableToNPCState(NPC* npc); 00475 void DoCompletionDecay(NPC* npc); 00478 void StartScript(NPC* npc); 00481 void OperationCompleted(NPC* npc); 00484 void OperationFailed(NPC* npc); 00485 void SetStartStep(); 00486 void InterruptScript(NPC* npc); 00487 bool IsInterrupted() 00488 { 00489 return interrupted; 00490 } 00491 void ClearInterrupted() 00492 { 00493 interrupted = false; 00494 } 00495 Behavior* SetCompletionDecay(float completion_decay) 00496 { 00497 this->completion_decay = completion_decay; 00498 return this; 00499 } 00500 00501 inline bool operator==(const Behavior &other) 00502 { 00503 return (current_need == other.current_need && 00504 name == other.name); 00505 } 00506 bool operator<(Behavior &other) 00507 { 00508 if(current_need > other.current_need) 00509 return true; 00510 if(current_need < other.current_need) 00511 return false; 00512 if(strcmp(name,other.name)>0) 00513 return true; 00514 return false; 00515 } 00516 00517 // For testing purposes only. 00518 00519 Behavior* SetDecay(float need_decay_rate) 00520 { 00521 this->need_decay_rate = need_decay_rate; 00522 return this; 00523 } 00524 Behavior* SetGrowth(float need_growth_rate) 00525 { 00526 this->need_growth_rate = need_growth_rate; 00527 return this; 00528 } 00529 Behavior* SetInitial(float init_need) 00530 { 00531 this->init_need = init_need; 00532 return this; 00533 } 00534 00539 void Failure(NPC* npc, ScriptOperation* op); 00540 }; 00541 00542 class psGameObject 00543 { 00544 public: 00552 static void GetPosition(gemNPCObject* object, csVector3 &pos, float &yrot, iSector* §or); 00553 00560 static void GetPosition(gemNPCObject* object, csVector3 &pos, iSector* §or); 00561 00562 static void SetPosition(gemNPCObject* objecty, const csVector3 &pos, iSector* = NULL); 00563 static void SetRotationAngle(gemNPCObject* object, float angle); 00564 static void GetRotationAngle(gemNPCObject* object, float &yrot) 00565 { 00566 csVector3 pos; 00567 iSector* sector; 00568 GetPosition(object,pos,yrot,sector); 00569 } 00573 static float CalculateIncidentAngle(const csVector3 &pos, const csVector3 &dest); 00574 00575 // Clamp the angle within 0 to 2*PI 00576 static void ClampRadians(float &target_angle); 00577 00578 // Normalize angle within -PI to PI 00579 static void NormalizeRadians(float &target_angle); 00580 00581 static csVector3 DisplaceTargetPos(const iSector* mySector, const csVector3 &myPos, 00582 const iSector* targetSector, const csVector3 &targetPos, 00583 float offset); 00584 static csVector3 DisplaceTargetPos(const iSector* mySector, const csVector3 &myPos, 00585 const iSector* targetSector, const csVector3 &targetPos, 00586 float offset, float angle); 00587 00588 static float Calc2DDistance(const csVector3 &a, const csVector3 &b); 00589 00598 static csString ReplaceNPCVariables(NPC* npc, const csString &object); 00599 00608 static bool ReplaceNPCVariablesBool(NPC* npc, const csString &object); 00609 00610 }; 00611 00614 #endif 00615