1 /* 2 ** p_acs.h 3 ** ACS script stuff 4 ** 5 **--------------------------------------------------------------------------- 6 ** Copyright 1998-2012 Randy Heit 7 ** All rights reserved. 8 ** 9 ** Redistribution and use in source and binary forms, with or without 10 ** modification, are permitted provided that the following conditions 11 ** are met: 12 ** 13 ** 1. Redistributions of source code must retain the above copyright 14 ** notice, this list of conditions and the following disclaimer. 15 ** 2. Redistributions in binary form must reproduce the above copyright 16 ** notice, this list of conditions and the following disclaimer in the 17 ** documentation and/or other materials provided with the distribution. 18 ** 3. The name of the author may not be used to endorse or promote products 19 ** derived from this software without specific prior written permission. 20 ** 21 ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 **--------------------------------------------------------------------------- 32 ** 33 */ 34 35 #ifndef __P_ACS_H__ 36 #define __P_ACS_H__ 37 38 #include "dobject.h" 39 #include "dthinker.h" 40 #include "doomtype.h" 41 42 #define LOCAL_SIZE 20 43 #define NUM_MAPVARS 128 44 45 class FFont; 46 class FileReader; 47 48 49 enum 50 { 51 NUM_WORLDVARS = 256, 52 NUM_GLOBALVARS = 64 53 }; 54 55 struct InitIntToZero 56 { InitInitIntToZero57 void Init(int &v) 58 { 59 v = 0; 60 } 61 }; 62 typedef TMap<SDWORD, SDWORD, THashTraits<SDWORD>, InitIntToZero> FWorldGlobalArray; 63 64 // ACS variables with world scope 65 extern SDWORD ACS_WorldVars[NUM_WORLDVARS]; 66 extern FWorldGlobalArray ACS_WorldArrays[NUM_WORLDVARS]; 67 68 // ACS variables with global scope 69 extern SDWORD ACS_GlobalVars[NUM_GLOBALVARS]; 70 extern FWorldGlobalArray ACS_GlobalArrays[NUM_GLOBALVARS]; 71 72 #define LIBRARYID_MASK 0xFFF00000 73 #define LIBRARYID_SHIFT 20 74 75 // Global ACS string table 76 #define STRPOOL_LIBRARYID (INT_MAX >> LIBRARYID_SHIFT) 77 #define STRPOOL_LIBRARYID_OR (STRPOOL_LIBRARYID << LIBRARYID_SHIFT) 78 79 class ACSStringPool 80 { 81 public: 82 ACSStringPool(); 83 int AddString(const char *str); 84 int AddString(FString &str); 85 const char *GetString(int strnum); 86 void LockString(int strnum); 87 void UnlockString(int strnum); 88 void UnlockAll(); 89 void MarkString(int strnum); 90 void LockStringArray(const int *strnum, unsigned int count); 91 void UnlockStringArray(const int *strnum, unsigned int count); 92 void MarkStringArray(const int *strnum, unsigned int count); 93 void MarkStringMap(const FWorldGlobalArray &array); 94 void PurgeStrings(); 95 void Clear(); 96 void Dump() const; 97 void ReadStrings(PNGHandle *png, DWORD id); 98 void WriteStrings(FILE *file, DWORD id) const; 99 100 private: 101 int FindString(const char *str, size_t len, unsigned int h, unsigned int bucketnum); 102 int InsertString(FString &str, unsigned int h, unsigned int bucketnum); 103 void FindFirstFreeEntry(unsigned int base); 104 105 enum { NUM_BUCKETS = 251 }; 106 enum { FREE_ENTRY = 0xFFFFFFFE }; // Stored in PoolEntry's Next field 107 enum { NO_ENTRY = 0xFFFFFFFF }; 108 enum { MIN_GC_SIZE = 100 }; // Don't auto-collect until there are this many strings 109 struct PoolEntry 110 { 111 FString Str; 112 unsigned int Hash; 113 unsigned int Next; 114 unsigned int LockCount; 115 }; 116 TArray<PoolEntry> Pool; 117 unsigned int PoolBuckets[NUM_BUCKETS]; 118 unsigned int FirstFreeEntry; 119 }; 120 extern ACSStringPool GlobalACSStrings; 121 122 void P_CollectACSGlobalStrings(); 123 void P_ReadACSVars(PNGHandle *); 124 void P_WriteACSVars(FILE*); 125 void P_ClearACSVars(bool); 126 void P_SerializeACSScriptNumber(FArchive &arc, int &scriptnum, bool was2byte); 127 128 struct ACSProfileInfo 129 { 130 unsigned long long TotalInstr; 131 unsigned int NumRuns; 132 unsigned int MinInstrPerRun; 133 unsigned int MaxInstrPerRun; 134 135 ACSProfileInfo(); 136 void AddRun(unsigned int num_instr); 137 void Reset(); 138 }; 139 140 struct ProfileCollector 141 { 142 ACSProfileInfo *ProfileData; 143 class FBehavior *Module; 144 int Index; 145 }; 146 147 struct ACSLocalArrayInfo 148 { 149 unsigned int Size; 150 int Offset; 151 }; 152 153 struct ACSLocalArrays 154 { 155 unsigned int Count; 156 ACSLocalArrayInfo *Info; 157 ACSLocalArraysACSLocalArrays158 ACSLocalArrays() 159 { 160 Count = 0; 161 Info = NULL; 162 } ~ACSLocalArraysACSLocalArrays163 ~ACSLocalArrays() 164 { 165 if (Info != NULL) 166 { 167 delete[] Info; 168 Info = NULL; 169 } 170 } 171 172 // Bounds-checking Set and Get for local arrays SetACSLocalArrays173 void Set(int *locals, int arraynum, int arrayentry, int value) 174 { 175 if ((unsigned int)arraynum < Count && 176 (unsigned int)arrayentry < Info[arraynum].Size) 177 { 178 locals[Info[arraynum].Offset + arrayentry] = value; 179 } 180 } GetACSLocalArrays181 int Get(int *locals, int arraynum, int arrayentry) 182 { 183 if ((unsigned int)arraynum < Count && 184 (unsigned int)arrayentry < Info[arraynum].Size) 185 { 186 return locals[Info[arraynum].Offset + arrayentry]; 187 } 188 return 0; 189 } 190 }; 191 192 // The in-memory version 193 struct ScriptPtr 194 { 195 int Number; 196 DWORD Address; 197 BYTE Type; 198 BYTE ArgCount; 199 WORD VarCount; 200 WORD Flags; 201 ACSLocalArrays LocalArrays; 202 203 ACSProfileInfo ProfileData; 204 }; 205 206 // The present ZDoom version 207 struct ScriptPtr3 208 { 209 SWORD Number; 210 BYTE Type; 211 BYTE ArgCount; 212 DWORD Address; 213 }; 214 215 // The intermediate ZDoom version 216 struct ScriptPtr1 217 { 218 SWORD Number; 219 WORD Type; 220 DWORD Address; 221 DWORD ArgCount; 222 }; 223 224 // The old Hexen version 225 struct ScriptPtr2 226 { 227 DWORD Number; // Type is Number / 1000 228 DWORD Address; 229 DWORD ArgCount; 230 }; 231 232 struct ScriptFlagsPtr 233 { 234 WORD Number; 235 WORD Flags; 236 }; 237 238 struct ScriptFunctionInFile 239 { 240 BYTE ArgCount; 241 BYTE LocalCount; 242 BYTE HasReturnValue; 243 BYTE ImportNum; 244 DWORD Address; 245 }; 246 247 struct ScriptFunction 248 { 249 BYTE ArgCount; 250 BYTE HasReturnValue; 251 BYTE ImportNum; 252 int LocalCount; 253 DWORD Address; 254 ACSLocalArrays LocalArrays; 255 }; 256 257 // Script types 258 enum 259 { 260 SCRIPT_Closed = 0, 261 SCRIPT_Open = 1, 262 SCRIPT_Respawn = 2, 263 SCRIPT_Death = 3, 264 SCRIPT_Enter = 4, 265 SCRIPT_Pickup = 5, 266 SCRIPT_BlueReturn = 6, 267 SCRIPT_RedReturn = 7, 268 SCRIPT_WhiteReturn = 8, 269 SCRIPT_Lightning = 12, 270 SCRIPT_Unloading = 13, 271 SCRIPT_Disconnect = 14, 272 SCRIPT_Return = 15, 273 }; 274 275 // Script flags 276 enum 277 { 278 SCRIPTF_Net = 0x0001 // Safe to "puke" in multiplayer 279 }; 280 281 enum ACSFormat { ACS_Old, ACS_Enhanced, ACS_LittleEnhanced, ACS_Unknown }; 282 283 class FBehavior 284 { 285 public: 286 FBehavior (); 287 ~FBehavior (); 288 bool Init(int lumpnum, FileReader * fr = NULL, int len = 0); 289 290 bool IsGood (); 291 BYTE *FindChunk (DWORD id) const; 292 BYTE *NextChunk (BYTE *chunk) const; 293 const ScriptPtr *FindScript (int number) const; 294 void StartTypedScripts (WORD type, AActor *activator, bool always, int arg1, bool runNow); PC2Ofs(int * pc)295 DWORD PC2Ofs (int *pc) const { return (DWORD)((BYTE *)pc - Data); } Ofs2PC(DWORD ofs)296 int *Ofs2PC (DWORD ofs) const { return (int *)(Data + ofs); } Jump2PC(DWORD jumpPoint)297 int *Jump2PC (DWORD jumpPoint) const { return Ofs2PC(JumpPoints[jumpPoint]); } GetFormat()298 ACSFormat GetFormat() const { return Format; } 299 ScriptFunction *GetFunction (int funcnum, FBehavior *&module) const; 300 int GetArrayVal (int arraynum, int index) const; 301 void SetArrayVal (int arraynum, int index, int value); 302 inline bool CopyStringToArray(int arraynum, int index, int maxLength, const char * string); 303 304 int FindFunctionName (const char *funcname) const; 305 int FindMapVarName (const char *varname) const; 306 int FindMapArray (const char *arrayname) const; GetLibraryID()307 int GetLibraryID () const { return LibraryID; } GetScriptAddress(const ScriptPtr * ptr)308 int *GetScriptAddress (const ScriptPtr *ptr) const { return (int *)(ptr->Address + Data); } GetScriptIndex(const ScriptPtr * ptr)309 int GetScriptIndex (const ScriptPtr *ptr) const { ptrdiff_t index = ptr - Scripts; return index >= NumScripts ? -1 : (int)index; } GetScriptPtr(int index)310 ScriptPtr *GetScriptPtr(int index) const { return index >= 0 && index < NumScripts ? &Scripts[index] : NULL; } GetLumpNum()311 int GetLumpNum() const { return LumpNum; } GetDataSize()312 int GetDataSize() const { return DataSize; } GetModuleName()313 const char *GetModuleName() const { return ModuleName; } GetFunctionProfileData(int index)314 ACSProfileInfo *GetFunctionProfileData(int index) { return index >= 0 && index < NumFunctions ? &FunctionProfileData[index] : NULL; } GetFunctionProfileData(ScriptFunction * func)315 ACSProfileInfo *GetFunctionProfileData(ScriptFunction *func) { return GetFunctionProfileData((int)(func - (ScriptFunction *)Functions)); } 316 const char *LookupString (DWORD index) const; 317 318 SDWORD *MapVars[NUM_MAPVARS]; 319 320 static FBehavior *StaticLoadModule (int lumpnum, FileReader * fr=NULL, int len=0); 321 static void StaticLoadDefaultModules (); 322 static void StaticUnloadModules (); 323 static bool StaticCheckAllGood (); 324 static FBehavior *StaticGetModule (int lib); 325 static void StaticSerializeModuleStates (FArchive &arc); 326 static void StaticMarkLevelVarStrings(); 327 static void StaticLockLevelVarStrings(); 328 static void StaticUnlockLevelVarStrings(); 329 330 static const ScriptPtr *StaticFindScript (int script, FBehavior *&module); 331 static const char *StaticLookupString (DWORD index); 332 static void StaticStartTypedScripts (WORD type, AActor *activator, bool always, int arg1=0, bool runNow=false); 333 static void StaticStopMyScripts (AActor *actor); 334 335 private: 336 struct ArrayInfo; 337 338 ACSFormat Format; 339 340 int LumpNum; 341 BYTE *Data; 342 int DataSize; 343 BYTE *Chunks; 344 ScriptPtr *Scripts; 345 int NumScripts; 346 ScriptFunction *Functions; 347 ACSProfileInfo *FunctionProfileData; 348 int NumFunctions; 349 ArrayInfo *ArrayStore; 350 int NumArrays; 351 ArrayInfo **Arrays; 352 int NumTotalArrays; 353 DWORD StringTable; 354 SDWORD MapVarStore[NUM_MAPVARS]; 355 TArray<FBehavior *> Imports; 356 DWORD LibraryID; 357 char ModuleName[9]; 358 TArray<int> JumpPoints; 359 360 static TArray<FBehavior *> StaticModules; 361 362 void LoadScriptsDirectory (); 363 364 static int STACK_ARGS SortScripts (const void *a, const void *b); 365 void UnencryptStrings (); 366 void UnescapeStringTable(BYTE *chunkstart, BYTE *datastart, bool haspadding); 367 int FindStringInChunk (DWORD *chunk, const char *varname) const; 368 369 void SerializeVars (FArchive &arc); 370 void SerializeVarSet (FArchive &arc, SDWORD *vars, int max); 371 372 void MarkMapVarStrings() const; 373 void LockMapVarStrings() const; 374 void UnlockMapVarStrings() const; 375 376 friend void ArrangeScriptProfiles(TArray<ProfileCollector> &profiles); 377 friend void ArrangeFunctionProfiles(TArray<ProfileCollector> &profiles); 378 }; 379 380 class DLevelScript : public DObject 381 { 382 DECLARE_CLASS (DLevelScript, DObject) 383 HAS_OBJECT_POINTERS 384 public: 385 386 // P-codes for ACS scripts 387 enum 388 { 389 /* 0*/ PCD_NOP, 390 PCD_TERMINATE, 391 PCD_SUSPEND, 392 PCD_PUSHNUMBER, 393 PCD_LSPEC1, 394 PCD_LSPEC2, 395 PCD_LSPEC3, 396 PCD_LSPEC4, 397 PCD_LSPEC5, 398 PCD_LSPEC1DIRECT, 399 /* 10*/ PCD_LSPEC2DIRECT, 400 PCD_LSPEC3DIRECT, 401 PCD_LSPEC4DIRECT, 402 PCD_LSPEC5DIRECT, 403 PCD_ADD, 404 PCD_SUBTRACT, 405 PCD_MULTIPLY, 406 PCD_DIVIDE, 407 PCD_MODULUS, 408 PCD_EQ, 409 /* 20*/ PCD_NE, 410 PCD_LT, 411 PCD_GT, 412 PCD_LE, 413 PCD_GE, 414 PCD_ASSIGNSCRIPTVAR, 415 PCD_ASSIGNMAPVAR, 416 PCD_ASSIGNWORLDVAR, 417 PCD_PUSHSCRIPTVAR, 418 PCD_PUSHMAPVAR, 419 /* 30*/ PCD_PUSHWORLDVAR, 420 PCD_ADDSCRIPTVAR, 421 PCD_ADDMAPVAR, 422 PCD_ADDWORLDVAR, 423 PCD_SUBSCRIPTVAR, 424 PCD_SUBMAPVAR, 425 PCD_SUBWORLDVAR, 426 PCD_MULSCRIPTVAR, 427 PCD_MULMAPVAR, 428 PCD_MULWORLDVAR, 429 /* 40*/ PCD_DIVSCRIPTVAR, 430 PCD_DIVMAPVAR, 431 PCD_DIVWORLDVAR, 432 PCD_MODSCRIPTVAR, 433 PCD_MODMAPVAR, 434 PCD_MODWORLDVAR, 435 PCD_INCSCRIPTVAR, 436 PCD_INCMAPVAR, 437 PCD_INCWORLDVAR, 438 PCD_DECSCRIPTVAR, 439 /* 50*/ PCD_DECMAPVAR, 440 PCD_DECWORLDVAR, 441 PCD_GOTO, 442 PCD_IFGOTO, 443 PCD_DROP, 444 PCD_DELAY, 445 PCD_DELAYDIRECT, 446 PCD_RANDOM, 447 PCD_RANDOMDIRECT, 448 PCD_THINGCOUNT, 449 /* 60*/ PCD_THINGCOUNTDIRECT, 450 PCD_TAGWAIT, 451 PCD_TAGWAITDIRECT, 452 PCD_POLYWAIT, 453 PCD_POLYWAITDIRECT, 454 PCD_CHANGEFLOOR, 455 PCD_CHANGEFLOORDIRECT, 456 PCD_CHANGECEILING, 457 PCD_CHANGECEILINGDIRECT, 458 PCD_RESTART, 459 /* 70*/ PCD_ANDLOGICAL, 460 PCD_ORLOGICAL, 461 PCD_ANDBITWISE, 462 PCD_ORBITWISE, 463 PCD_EORBITWISE, 464 PCD_NEGATELOGICAL, 465 PCD_LSHIFT, 466 PCD_RSHIFT, 467 PCD_UNARYMINUS, 468 PCD_IFNOTGOTO, 469 /* 80*/ PCD_LINESIDE, 470 PCD_SCRIPTWAIT, 471 PCD_SCRIPTWAITDIRECT, 472 PCD_CLEARLINESPECIAL, 473 PCD_CASEGOTO, 474 PCD_BEGINPRINT, 475 PCD_ENDPRINT, 476 PCD_PRINTSTRING, 477 PCD_PRINTNUMBER, 478 PCD_PRINTCHARACTER, 479 /* 90*/ PCD_PLAYERCOUNT, 480 PCD_GAMETYPE, 481 PCD_GAMESKILL, 482 PCD_TIMER, 483 PCD_SECTORSOUND, 484 PCD_AMBIENTSOUND, 485 PCD_SOUNDSEQUENCE, 486 PCD_SETLINETEXTURE, 487 PCD_SETLINEBLOCKING, 488 PCD_SETLINESPECIAL, 489 /*100*/ PCD_THINGSOUND, 490 PCD_ENDPRINTBOLD, // [RH] End of Hexen p-codes 491 PCD_ACTIVATORSOUND, 492 PCD_LOCALAMBIENTSOUND, 493 PCD_SETLINEMONSTERBLOCKING, 494 PCD_PLAYERBLUESKULL, // [BC] Start of new [Skull Tag] pcodes 495 PCD_PLAYERREDSKULL, 496 PCD_PLAYERYELLOWSKULL, 497 PCD_PLAYERMASTERSKULL, 498 PCD_PLAYERBLUECARD, 499 /*110*/ PCD_PLAYERREDCARD, 500 PCD_PLAYERYELLOWCARD, 501 PCD_PLAYERMASTERCARD, 502 PCD_PLAYERBLACKSKULL, 503 PCD_PLAYERSILVERSKULL, 504 PCD_PLAYERGOLDSKULL, 505 PCD_PLAYERBLACKCARD, 506 PCD_PLAYERSILVERCARD, 507 PCD_PLAYERONTEAM, 508 PCD_PLAYERTEAM, 509 /*120*/ PCD_PLAYERHEALTH, 510 PCD_PLAYERARMORPOINTS, 511 PCD_PLAYERFRAGS, 512 PCD_PLAYEREXPERT, 513 PCD_BLUETEAMCOUNT, 514 PCD_REDTEAMCOUNT, 515 PCD_BLUETEAMSCORE, 516 PCD_REDTEAMSCORE, 517 PCD_ISONEFLAGCTF, 518 PCD_LSPEC6, // These are never used. They should probably 519 /*130*/ PCD_LSPEC6DIRECT, // be given names like PCD_DUMMY. 520 PCD_PRINTNAME, 521 PCD_MUSICCHANGE, 522 PCD_TEAM2FRAGPOINTS, 523 PCD_CONSOLECOMMAND, 524 PCD_SINGLEPLAYER, // [RH] End of Skull Tag p-codes 525 PCD_FIXEDMUL, 526 PCD_FIXEDDIV, 527 PCD_SETGRAVITY, 528 PCD_SETGRAVITYDIRECT, 529 /*140*/ PCD_SETAIRCONTROL, 530 PCD_SETAIRCONTROLDIRECT, 531 PCD_CLEARINVENTORY, 532 PCD_GIVEINVENTORY, 533 PCD_GIVEINVENTORYDIRECT, 534 PCD_TAKEINVENTORY, 535 PCD_TAKEINVENTORYDIRECT, 536 PCD_CHECKINVENTORY, 537 PCD_CHECKINVENTORYDIRECT, 538 PCD_SPAWN, 539 /*150*/ PCD_SPAWNDIRECT, 540 PCD_SPAWNSPOT, 541 PCD_SPAWNSPOTDIRECT, 542 PCD_SETMUSIC, 543 PCD_SETMUSICDIRECT, 544 PCD_LOCALSETMUSIC, 545 PCD_LOCALSETMUSICDIRECT, 546 PCD_PRINTFIXED, 547 PCD_PRINTLOCALIZED, 548 PCD_MOREHUDMESSAGE, 549 /*160*/ PCD_OPTHUDMESSAGE, 550 PCD_ENDHUDMESSAGE, 551 PCD_ENDHUDMESSAGEBOLD, 552 PCD_SETSTYLE, 553 PCD_SETSTYLEDIRECT, 554 PCD_SETFONT, 555 PCD_SETFONTDIRECT, 556 PCD_PUSHBYTE, 557 PCD_LSPEC1DIRECTB, 558 PCD_LSPEC2DIRECTB, 559 /*170*/ PCD_LSPEC3DIRECTB, 560 PCD_LSPEC4DIRECTB, 561 PCD_LSPEC5DIRECTB, 562 PCD_DELAYDIRECTB, 563 PCD_RANDOMDIRECTB, 564 PCD_PUSHBYTES, 565 PCD_PUSH2BYTES, 566 PCD_PUSH3BYTES, 567 PCD_PUSH4BYTES, 568 PCD_PUSH5BYTES, 569 /*180*/ PCD_SETTHINGSPECIAL, 570 PCD_ASSIGNGLOBALVAR, 571 PCD_PUSHGLOBALVAR, 572 PCD_ADDGLOBALVAR, 573 PCD_SUBGLOBALVAR, 574 PCD_MULGLOBALVAR, 575 PCD_DIVGLOBALVAR, 576 PCD_MODGLOBALVAR, 577 PCD_INCGLOBALVAR, 578 PCD_DECGLOBALVAR, 579 /*190*/ PCD_FADETO, 580 PCD_FADERANGE, 581 PCD_CANCELFADE, 582 PCD_PLAYMOVIE, 583 PCD_SETFLOORTRIGGER, 584 PCD_SETCEILINGTRIGGER, 585 PCD_GETACTORX, 586 PCD_GETACTORY, 587 PCD_GETACTORZ, 588 PCD_STARTTRANSLATION, 589 /*200*/ PCD_TRANSLATIONRANGE1, 590 PCD_TRANSLATIONRANGE2, 591 PCD_ENDTRANSLATION, 592 PCD_CALL, 593 PCD_CALLDISCARD, 594 PCD_RETURNVOID, 595 PCD_RETURNVAL, 596 PCD_PUSHMAPARRAY, 597 PCD_ASSIGNMAPARRAY, 598 PCD_ADDMAPARRAY, 599 /*210*/ PCD_SUBMAPARRAY, 600 PCD_MULMAPARRAY, 601 PCD_DIVMAPARRAY, 602 PCD_MODMAPARRAY, 603 PCD_INCMAPARRAY, 604 PCD_DECMAPARRAY, 605 PCD_DUP, 606 PCD_SWAP, 607 PCD_WRITETOINI, 608 PCD_GETFROMINI, 609 /*220*/ PCD_SIN, 610 PCD_COS, 611 PCD_VECTORANGLE, 612 PCD_CHECKWEAPON, 613 PCD_SETWEAPON, 614 PCD_TAGSTRING, 615 PCD_PUSHWORLDARRAY, 616 PCD_ASSIGNWORLDARRAY, 617 PCD_ADDWORLDARRAY, 618 PCD_SUBWORLDARRAY, 619 /*230*/ PCD_MULWORLDARRAY, 620 PCD_DIVWORLDARRAY, 621 PCD_MODWORLDARRAY, 622 PCD_INCWORLDARRAY, 623 PCD_DECWORLDARRAY, 624 PCD_PUSHGLOBALARRAY, 625 PCD_ASSIGNGLOBALARRAY, 626 PCD_ADDGLOBALARRAY, 627 PCD_SUBGLOBALARRAY, 628 PCD_MULGLOBALARRAY, 629 /*240*/ PCD_DIVGLOBALARRAY, 630 PCD_MODGLOBALARRAY, 631 PCD_INCGLOBALARRAY, 632 PCD_DECGLOBALARRAY, 633 PCD_SETMARINEWEAPON, 634 PCD_SETACTORPROPERTY, 635 PCD_GETACTORPROPERTY, 636 PCD_PLAYERNUMBER, 637 PCD_ACTIVATORTID, 638 PCD_SETMARINESPRITE, 639 /*250*/ PCD_GETSCREENWIDTH, 640 PCD_GETSCREENHEIGHT, 641 PCD_THING_PROJECTILE2, 642 PCD_STRLEN, 643 PCD_SETHUDSIZE, 644 PCD_GETCVAR, 645 PCD_CASEGOTOSORTED, 646 PCD_SETRESULTVALUE, 647 PCD_GETLINEROWOFFSET, 648 PCD_GETACTORFLOORZ, 649 /*260*/ PCD_GETACTORANGLE, 650 PCD_GETSECTORFLOORZ, 651 PCD_GETSECTORCEILINGZ, 652 PCD_LSPEC5RESULT, 653 PCD_GETSIGILPIECES, 654 PCD_GETLEVELINFO, 655 PCD_CHANGESKY, 656 PCD_PLAYERINGAME, 657 PCD_PLAYERISBOT, 658 PCD_SETCAMERATOTEXTURE, 659 /*270*/ PCD_ENDLOG, 660 PCD_GETAMMOCAPACITY, 661 PCD_SETAMMOCAPACITY, 662 PCD_PRINTMAPCHARARRAY, // [JB] start of new p-codes 663 PCD_PRINTWORLDCHARARRAY, 664 PCD_PRINTGLOBALCHARARRAY, // [JB] end of new p-codes 665 PCD_SETACTORANGLE, // [GRB] 666 PCD_GRABINPUT, // Unused but acc defines them 667 PCD_SETMOUSEPOINTER, // " 668 PCD_MOVEMOUSEPOINTER, // " 669 /*280*/ PCD_SPAWNPROJECTILE, 670 PCD_GETSECTORLIGHTLEVEL, 671 PCD_GETACTORCEILINGZ, 672 PCD_SETACTORPOSITION, 673 PCD_CLEARACTORINVENTORY, 674 PCD_GIVEACTORINVENTORY, 675 PCD_TAKEACTORINVENTORY, 676 PCD_CHECKACTORINVENTORY, 677 PCD_THINGCOUNTNAME, 678 PCD_SPAWNSPOTFACING, 679 /*290*/ PCD_PLAYERCLASS, // [GRB] 680 //[MW] start my p-codes 681 PCD_ANDSCRIPTVAR, 682 PCD_ANDMAPVAR, 683 PCD_ANDWORLDVAR, 684 PCD_ANDGLOBALVAR, 685 PCD_ANDMAPARRAY, 686 PCD_ANDWORLDARRAY, 687 PCD_ANDGLOBALARRAY, 688 PCD_EORSCRIPTVAR, 689 PCD_EORMAPVAR, 690 /*300*/ PCD_EORWORLDVAR, 691 PCD_EORGLOBALVAR, 692 PCD_EORMAPARRAY, 693 PCD_EORWORLDARRAY, 694 PCD_EORGLOBALARRAY, 695 PCD_ORSCRIPTVAR, 696 PCD_ORMAPVAR, 697 PCD_ORWORLDVAR, 698 PCD_ORGLOBALVAR, 699 PCD_ORMAPARRAY, 700 /*310*/ PCD_ORWORLDARRAY, 701 PCD_ORGLOBALARRAY, 702 PCD_LSSCRIPTVAR, 703 PCD_LSMAPVAR, 704 PCD_LSWORLDVAR, 705 PCD_LSGLOBALVAR, 706 PCD_LSMAPARRAY, 707 PCD_LSWORLDARRAY, 708 PCD_LSGLOBALARRAY, 709 PCD_RSSCRIPTVAR, 710 /*320*/ PCD_RSMAPVAR, 711 PCD_RSWORLDVAR, 712 PCD_RSGLOBALVAR, 713 PCD_RSMAPARRAY, 714 PCD_RSWORLDARRAY, 715 PCD_RSGLOBALARRAY, 716 //[MW] end my p-codes 717 PCD_GETPLAYERINFO, // [GRB] 718 PCD_CHANGELEVEL, 719 PCD_SECTORDAMAGE, 720 PCD_REPLACETEXTURES, 721 /*330*/ PCD_NEGATEBINARY, 722 PCD_GETACTORPITCH, 723 PCD_SETACTORPITCH, 724 PCD_PRINTBIND, 725 PCD_SETACTORSTATE, 726 PCD_THINGDAMAGE2, 727 PCD_USEINVENTORY, 728 PCD_USEACTORINVENTORY, 729 PCD_CHECKACTORCEILINGTEXTURE, 730 PCD_CHECKACTORFLOORTEXTURE, 731 /*340*/ PCD_GETACTORLIGHTLEVEL, 732 PCD_SETMUGSHOTSTATE, 733 PCD_THINGCOUNTSECTOR, 734 PCD_THINGCOUNTNAMESECTOR, 735 PCD_CHECKPLAYERCAMERA, // [TN] 736 PCD_MORPHACTOR, // [MH] 737 PCD_UNMORPHACTOR, // [MH] 738 PCD_GETPLAYERINPUT, 739 PCD_CLASSIFYACTOR, 740 PCD_PRINTBINARY, 741 /*350*/ PCD_PRINTHEX, 742 PCD_CALLFUNC, 743 PCD_SAVESTRING, // [FDARI] create string (temporary) 744 PCD_PRINTMAPCHRANGE, // [FDARI] output range (print part of array) 745 PCD_PRINTWORLDCHRANGE, 746 PCD_PRINTGLOBALCHRANGE, 747 PCD_STRCPYTOMAPCHRANGE, // [FDARI] input range (copy string to all/part of array) 748 PCD_STRCPYTOWORLDCHRANGE, 749 PCD_STRCPYTOGLOBALCHRANGE, 750 PCD_PUSHFUNCTION, // from Eternity 751 /*360*/ PCD_CALLSTACK, // from Eternity 752 PCD_SCRIPTWAITNAMED, 753 PCD_TRANSLATIONRANGE3, 754 PCD_GOTOSTACK, 755 PCD_ASSIGNSCRIPTARRAY, 756 PCD_PUSHSCRIPTARRAY, 757 PCD_ADDSCRIPTARRAY, 758 PCD_SUBSCRIPTARRAY, 759 PCD_MULSCRIPTARRAY, 760 PCD_DIVSCRIPTARRAY, 761 /*370*/ PCD_MODSCRIPTARRAY, 762 PCD_INCSCRIPTARRAY, 763 PCD_DECSCRIPTARRAY, 764 PCD_ANDSCRIPTARRAY, 765 PCD_EORSCRIPTARRAY, 766 PCD_ORSCRIPTARRAY, 767 PCD_LSSCRIPTARRAY, 768 PCD_RSSCRIPTARRAY, 769 PCD_PRINTSCRIPTCHARARRAY, 770 PCD_PRINTSCRIPTCHRANGE, 771 /*380*/ PCD_STRCPYTOSCRIPTCHRANGE, 772 773 /*381*/ PCODE_COMMAND_COUNT 774 }; 775 776 // Some constants used by ACS scripts 777 enum { 778 LINE_FRONT = 0, 779 LINE_BACK = 1 780 }; 781 enum { 782 SIDE_FRONT = 0, 783 SIDE_BACK = 1 784 }; 785 enum { 786 TEXTURE_TOP = 0, 787 TEXTURE_MIDDLE = 1, 788 TEXTURE_BOTTOM = 2 789 }; 790 enum { 791 GAME_SINGLE_PLAYER = 0, 792 GAME_NET_COOPERATIVE = 1, 793 GAME_NET_DEATHMATCH = 2, 794 GAME_TITLE_MAP = 3 795 }; 796 enum { 797 CLASS_FIGHTER = 0, 798 CLASS_CLERIC = 1, 799 CLASS_MAGE = 2 800 }; 801 enum { 802 SKILL_VERY_EASY = 0, 803 SKILL_EASY = 1, 804 SKILL_NORMAL = 2, 805 SKILL_HARD = 3, 806 SKILL_VERY_HARD = 4 807 }; 808 enum { 809 BLOCK_NOTHING = 0, 810 BLOCK_CREATURES = 1, 811 BLOCK_EVERYTHING = 2, 812 BLOCK_RAILING = 3, 813 BLOCK_PLAYERS = 4 814 }; 815 enum { 816 LEVELINFO_PAR_TIME, 817 LEVELINFO_CLUSTERNUM, 818 LEVELINFO_LEVELNUM, 819 LEVELINFO_TOTAL_SECRETS, 820 LEVELINFO_FOUND_SECRETS, 821 LEVELINFO_TOTAL_ITEMS, 822 LEVELINFO_FOUND_ITEMS, 823 LEVELINFO_TOTAL_MONSTERS, 824 LEVELINFO_KILLED_MONSTERS, 825 LEVELINFO_SUCK_TIME 826 }; 827 enum { 828 PLAYERINFO_TEAM, 829 PLAYERINFO_AIMDIST, 830 PLAYERINFO_COLOR, 831 PLAYERINFO_GENDER, 832 PLAYERINFO_NEVERSWITCH, 833 PLAYERINFO_MOVEBOB, 834 PLAYERINFO_STILLBOB, 835 PLAYERINFO_PLAYERCLASS, 836 PLAYERINFO_FOV, 837 PLAYERINFO_DESIREDFOV, 838 }; 839 840 enum EScriptState 841 { 842 SCRIPT_Running, 843 SCRIPT_Suspended, 844 SCRIPT_Delayed, 845 SCRIPT_TagWait, 846 SCRIPT_PolyWait, 847 SCRIPT_ScriptWaitPre, 848 SCRIPT_ScriptWait, 849 SCRIPT_PleaseRemove, 850 SCRIPT_DivideBy0, 851 SCRIPT_ModulusBy0, 852 }; 853 854 DLevelScript (AActor *who, line_t *where, int num, const ScriptPtr *code, FBehavior *module, 855 const int *args, int argcount, int flags); 856 ~DLevelScript (); 857 858 void Serialize (FArchive &arc); 859 int RunScript (); 860 SetState(EScriptState newstate)861 inline void SetState (EScriptState newstate) { state = newstate; } GetState()862 inline EScriptState GetState () { return state; } 863 GetNext()864 DLevelScript *GetNext() const { return next; } 865 MarkLocalVarStrings()866 void MarkLocalVarStrings() const 867 { 868 GlobalACSStrings.MarkStringArray(localvars, numlocalvars); 869 } LockLocalVarStrings()870 void LockLocalVarStrings() const 871 { 872 GlobalACSStrings.LockStringArray(localvars, numlocalvars); 873 } UnlockLocalVarStrings()874 void UnlockLocalVarStrings() const 875 { 876 GlobalACSStrings.UnlockStringArray(localvars, numlocalvars); 877 } 878 879 protected: 880 DLevelScript *next, *prev; 881 int script; 882 SDWORD *localvars; 883 int numlocalvars; 884 int *pc; 885 EScriptState state; 886 int statedata; 887 TObjPtr<AActor> activator; 888 line_t *activationline; 889 bool backSide; 890 FFont *activefont; 891 int hudwidth, hudheight; 892 int ClipRectLeft, ClipRectTop, ClipRectWidth, ClipRectHeight; 893 int WrapWidth; 894 bool HandleAspect; 895 FBehavior *activeBehavior; 896 int InModuleScriptNumber; 897 898 void Link (); 899 void Unlink (); 900 void PutLast (); 901 void PutFirst (); 902 static int Random (int min, int max); 903 static int ThingCount (int type, int stringid, int tid, int tag); 904 static void ChangeFlat (int tag, int name, bool floorOrCeiling); 905 static int CountPlayers (); 906 static void SetLineTexture (int lineid, int side, int position, int name); 907 static void ReplaceTextures (int fromname, int toname, int flags); 908 static int DoSpawn (int type, fixed_t x, fixed_t y, fixed_t z, int tid, int angle, bool force); 909 static bool DoCheckActorTexture(int tid, AActor *activator, int string, bool floor); 910 int DoSpawnSpot (int type, int spot, int tid, int angle, bool forced); 911 int DoSpawnSpotFacing (int type, int spot, int tid, bool forced); 912 int DoClassifyActor (int tid); 913 int CallFunction(int argCount, int funcIndex, SDWORD *args); 914 915 void DoFadeTo (int r, int g, int b, int a, fixed_t time); 916 void DoFadeRange (int r1, int g1, int b1, int a1, 917 int r2, int g2, int b2, int a2, fixed_t time); 918 void DoSetFont (int fontnum); 919 void SetActorProperty (int tid, int property, int value); 920 void DoSetActorProperty (AActor *actor, int property, int value); 921 int GetActorProperty (int tid, int property); 922 int CheckActorProperty (int tid, int property, int value); 923 int GetPlayerInput (int playernum, int inputnum); 924 925 int LineFromID(int id); 926 int SideFromID(int id, int side); 927 928 private: 929 DLevelScript (); 930 931 friend class DACSThinker; 932 }; 933 934 class DACSThinker : public DThinker 935 { 936 DECLARE_CLASS (DACSThinker, DThinker) 937 HAS_OBJECT_POINTERS 938 public: 939 DACSThinker (); 940 ~DACSThinker (); 941 942 void Serialize (FArchive &arc); 943 void Tick (); 944 945 typedef TMap<int, DLevelScript *> ScriptMap; 946 ScriptMap RunningScripts; // Array of all synchronous scripts 947 static TObjPtr<DACSThinker> ActiveThinker; 948 949 void DumpScriptStatus(); 950 void StopScriptsFor (AActor *actor); 951 952 private: 953 DLevelScript *LastScript; 954 DLevelScript *Scripts; // List of all running scripts 955 956 friend class DLevelScript; 957 friend class FBehavior; 958 }; 959 960 // The structure used to control scripts between maps 961 struct acsdefered_t 962 { 963 struct acsdefered_t *next; 964 965 enum EType 966 { 967 defexecute, 968 defexealways, 969 defsuspend, 970 defterminate 971 } type; 972 int script; 973 int args[3]; 974 int playernum; 975 }; 976 977 FArchive &operator<< (FArchive &arc, acsdefered_t *&defer); 978 979 #endif //__P_ACS_H__ 980