static void AddOneKey(Keygroup *keygroup, PClassActor *mi, FScanner &sc) { if (mi) { // Any inventory item can be used to unlock a door if (mi->IsDescendantOf(RUNTIME_CLASS(AInventory))) { OneKey k = {mi,1}; keygroup->anykeylist.Push (k); //... but only keys get key numbers! if (mi->IsDescendantOf(RUNTIME_CLASS(AKey))) { if (!ignorekey && static_cast<AKey*>(GetDefaultByType(mi))->KeyNumber == 0) { static_cast<AKey*>(GetDefaultByType(mi))->KeyNumber=++currentnumber; } } } else { sc.ScriptError("'%s' is not an inventory item", sc.String); } } else { sc.ScriptError("Unknown item '%s'", sc.String); } }
void AScriptedMarine::SetWeapon (EMarineWeapon type) { if (GetWeaponStates(type, MeleeState, MissileState)) { static const char *classes[] = { "ScriptedMarine", "MarineFist", "MarineBerserk", "MarineChainsaw", "MarinePistol", "MarineShotgun", "MarineSSG", "MarineChaingun", "MarineRocket", "MarinePlasma", "MarineRailgun", "MarineBFG" }; const PClass *cls = PClass::FindClass(classes[type]); if (cls != NULL) DecalGenerator = GetDefaultByType(cls)->DecalGenerator; else DecalGenerator = NULL; } }
static void SetKeyTypes() { for(unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); i++) { PClass *ti = PClassActor::AllActorClasses[i]; auto kt = PClass::FindActor(NAME_Key); if (ti->IsDescendantOf(kt)) { PClassActor *tia = static_cast<PClassActor *>(ti); AInventory *key = (AInventory*)(GetDefaultByType(tia)); if (key->Icon.isValid() && key->special1 > 0) { KeyTypes.Push(tia); } else { UnassignedKeyTypes.Push(tia); } } } if (KeyTypes.Size()) { qsort(&KeyTypes[0], KeyTypes.Size(), sizeof(KeyTypes[0]), ktcmp); } else { // Don't leave the list empty KeyTypes.Push(PClass::FindActor(NAME_Key)); } }
void AScriptedMarine::SetSprite (PClassActor *source) { if (source == NULL) { // A valid actor class wasn't passed, so use the standard sprite SpriteOverride = sprite = GetClass()->OwnedStates[0].sprite; // Copy the standard scaling scaleX = GetDefault()->scaleX; scaleY = GetDefault()->scaleY; } else { // Use the same sprite and scaling the passed class spawns with SpriteOverride = sprite = GetDefaultByType (source)->SpawnState->sprite; scaleX = GetDefaultByType(source)->scaleX; scaleY = GetDefaultByType(source)->scaleY; } }
static void ClearLocks() { unsigned int i; for(i = 0; i < PClassActor::AllActorClasses.Size(); i++) { if (PClassActor::AllActorClasses[i]->IsDescendantOf(RUNTIME_CLASS(AKey))) { AKey *key = static_cast<AKey*>(GetDefaultByType(PClassActor::AllActorClasses[i])); if (key != NULL) { key->KeyNumber = 0; } } } for(i = 0; i < 256; i++) { if (locks[i] != NULL) { delete locks[i]; locks[i] = NULL; } } currentnumber = 0; keysdone = false; }
DEFINE_ACTION_FUNCTION(AActor, A_PotteryExplode) { AActor *mo = NULL; int i; for(i = (pr_pottery()&3)+3; i; i--) { mo = Spawn ("PotteryBit", self->x, self->y, self->z, ALLOW_REPLACE); if (mo) { mo->SetState (mo->SpawnState + (pr_pottery()%5)); mo->velz = ((pr_pottery()&7)+5)*(3*FRACUNIT/4); mo->velx = (pr_pottery.Random2())<<(FRACBITS-6); mo->vely = (pr_pottery.Random2())<<(FRACBITS-6); } } S_Sound (mo, CHAN_BODY, "PotteryExplode", 1, ATTN_NORM); // Spawn an item? const PClass *type = P_GetSpawnableType(self->args[0]); if (type != NULL) { if (!((level.flags2 & LEVEL2_NOMONSTERS) || (dmflags & DF_NO_MONSTERS)) || !(GetDefaultByType (type)->flags3 & MF3_ISMONSTER)) { // Only spawn monsters if not -nomonsters Spawn (type, self->x, self->y, self->z, ALLOW_REPLACE); } } }
DEFINE_ACTION_FUNCTION(AActor, A_SoAExplode) { AActor *mo; int i; for (i = 0; i < 10; i++) { mo = Spawn ("ZArmorChunk", self->x+((pr_soaexplode()-128)<<12), self->y+((pr_soaexplode()-128)<<12), self->z+(pr_soaexplode()*self->height/256), ALLOW_REPLACE); if (mo) { mo->SetState (mo->SpawnState + i); mo->velz = ((pr_soaexplode()&7)+5)*FRACUNIT; mo->velx = pr_soaexplode.Random2()<<(FRACBITS-6); mo->vely = pr_soaexplode.Random2()<<(FRACBITS-6); } } // Spawn an item? const PClass *type = P_GetSpawnableType(self->args[0]); if (type != NULL) { if (!((level.flags2 & LEVEL2_NOMONSTERS) || (dmflags & DF_NO_MONSTERS)) || !(GetDefaultByType (type)->flags3 & MF3_ISMONSTER)) { // Only spawn monsters if not -nomonsters Spawn (type, self->x, self->y, self->z, ALLOW_REPLACE); } } S_Sound (self, CHAN_BODY, self->DeathSound, 1, ATTN_NORM); self->Destroy (); }
FSpriteModelFrame * gl_FindModelFrame(const PClass * ti, int sprite, int frame) { // [BB] The user doesn't want to use models, so just pretend that there is no model for this frame. if ( gl_use_models == false ) return NULL; if (GetDefaultByType(ti)->hasmodel) { FSpriteModelFrame smf; memset(&smf, 0, sizeof(smf)); smf.type=ti; smf.sprite=sprite; smf.frame=frame; int hash = SpriteModelHash[ModelFrameHash(&smf) % SpriteModelFrames.Size()]; while (hash>=0) { FSpriteModelFrame * smff = &SpriteModelFrames[hash]; if (smff->type==ti && smff->sprite==sprite && smff->frame==frame) return smff; hash=smff->hashnext; } } return NULL; }
static void SetKeyTypes() { for(unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); i++) { PClass *ti = PClassActor::AllActorClasses[i]; if (ti->IsDescendantOf(RUNTIME_CLASS(AKey))) { PClassActor *tia = static_cast<PClassActor *>(ti); AKey *key = (AKey*)GetDefaultByType(tia); if (key->Icon.isValid() && key->KeyNumber>0) { KeyTypes.Push(tia); } else { UnassignedKeyTypes.Push(tia); } } } if (KeyTypes.Size()) { qsort(&KeyTypes[0], KeyTypes.Size(), sizeof(KeyTypes[0]), ktcmp); } else { // Don't leave the list empty PClassActor *ti = RUNTIME_CLASS(AKey); KeyTypes.Push(ti); } }
bool AClericWeaponPiece::TryPickup (AActor *&toucher) { if (!toucher->IsKindOf (PClass::FindClass(NAME_MagePlayer)) && !toucher->IsKindOf (PClass::FindClass(NAME_FighterPlayer))) { return Super::TryPickup(toucher); } else { // Wrong class, but try to pick up for ammo if (ShouldStay()) { // Can't pick up weapons for other classes in coop netplay return false; } AWeapon * Defaults=(AWeapon*)GetDefaultByType(WeaponClass); bool gaveSome = !!(toucher->GiveAmmo (Defaults->AmmoType1, Defaults->AmmoGive1) + toucher->GiveAmmo (Defaults->AmmoType2, Defaults->AmmoGive2)); if (gaveSome) { GoAwayAndDie (); } return gaveSome; } }
void AScriptedMarine::SetSprite (const PClass *source) { if (source == NULL || source->ActorInfo == NULL) { // A valid actor class wasn't passed, so use the standard sprite SpriteOverride = sprite = GetClass()->ActorInfo->OwnedStates[0].sprite; // Copy the standard player's scaling AActor * playerdef = GetDefaultByName("DoomPlayer"); if (playerdef == NULL) playerdef = GetDefaultByType(RUNTIME_CLASS(AScriptedMarine)); scaleX = playerdef->scaleX; scaleY = playerdef->scaleY; } else { // Use the same sprite the passed class spawns with SpriteOverride = sprite = GetDefaultByType (source)->SpawnState->sprite; scaleX = GetDefaultByType(source)->scaleX; scaleY = GetDefaultByType(source)->scaleY; } }
void gl_InitializeActorLights() { for(unsigned int i=0;i<LightAssociations.Size();i++) { const PClass * ti = PClass::FindClass(LightAssociations[i].ActorName()); if (ti) { ti = GetRealType(ti); AActor * defaults = GetDefaultByType(ti); if (defaults) { FInternalLightAssociation * iasso = new FInternalLightAssociation(&LightAssociations[i]); if (!defaults->lightassociations) { TDeletingArray<FInternalLightAssociation*> *p =new TDeletingArray<FInternalLightAssociation*>; defaults->lightassociations = p; AssoDeleter.Push(p); } TDeletingArray<FInternalLightAssociation *> * lights = gl_GetActorLights(defaults); if (iasso->Light()==NULL) { // The definition was not valid. delete iasso; } else { lights->Push(iasso); } } } } // we don't need the parser data for the light associations anymore LightAssociations.Clear(); LightAssociations.ShrinkToFit(); StateLights.Resize(ParsedStateLights.Size()+1); for(unsigned i=0; i<ParsedStateLights.Size();i++) { if (ParsedStateLights[i] != NAME_None) { StateLights[i] = (FLightDefaults*)-1; // something invalid that's not NULL. for(unsigned int j=0;j<LightDefaults.Size();j++) { if (LightDefaults[j]->GetName() == ParsedStateLights[i]) { StateLights[i] = LightDefaults[j]; break; } } } else StateLights[i] = NULL; } StateLights[StateLights.Size()-1] = NULL; // terminator ParsedStateLights.Clear(); ParsedStateLights.ShrinkToFit(); }
static bool IsMonster(const FDropItem *di) { const PClass *pclass = PClass::FindClass(di->Name); if (NULL == pclass) { return false; } return 0 != (GetDefaultByType(pclass)->flags3 & MF3_ISMONSTER); }
AInventory *ABackpackItem::CreateCopy (AActor *other) { // Find every unique type of ammo. Give it to the player if // he doesn't have it already, and double its maximum capacity. for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); ++i) { PClass *type = PClassActor::AllActorClasses[i]; if (type->ParentClass == RUNTIME_CLASS(AAmmo)) { PClassActor *atype = static_cast<PClassActor *>(type); AAmmo *ammo = static_cast<AAmmo *>(other->FindInventory(atype)); int amount = static_cast<AAmmo *>(GetDefaultByType(type))->BackpackAmount; // extra ammo in baby mode and nightmare mode if (!(ItemFlags&IF_IGNORESKILL)) { amount = int(amount * G_SkillProperty(SKILLP_AmmoFactor)); } if (amount < 0) amount = 0; if (ammo == NULL) { // The player did not have the ammo. Add it. ammo = static_cast<AAmmo *>(Spawn(atype)); ammo->Amount = bDepleted ? 0 : amount; if (ammo->BackpackMaxAmount > ammo->MaxAmount) { ammo->MaxAmount = ammo->BackpackMaxAmount; } if (ammo->Amount > ammo->MaxAmount) { ammo->Amount = ammo->MaxAmount; } ammo->AttachToOwner (other); } else { // The player had the ammo. Give some more. if (ammo->MaxAmount < ammo->BackpackMaxAmount) { ammo->MaxAmount = ammo->BackpackMaxAmount; } if (!bDepleted && ammo->Amount < ammo->MaxAmount) { ammo->Amount += amount; if (ammo->Amount > ammo->MaxAmount) { ammo->Amount = ammo->MaxAmount; } } } } } return Super::CreateCopy (other); }
static void GetAmmoTextLengths(player_t *CPlayer, int& ammocur, int& ammomax) { for (auto type : orderedammos) { auto ammoitem = CPlayer->mo->FindInventory(type); auto inv = nullptr == ammoitem ? static_cast<AInventory*>(GetDefaultByType(type)) : ammoitem; assert(nullptr != inv); ammocur = MAX(ammocur, nullptr == ammoitem ? 0 : ammoitem->Amount); ammomax = MAX(ammomax, inv->MaxAmount); } ammocur = GetDigitCount(ammocur); ammomax = GetDigitCount(ammomax); }
void DIntermissionScreenCast::Init(FIntermissionAction *desc, bool first) { Super::Init(desc, first); mName = static_cast<FIntermissionActionCast*>(desc)->mName; mClass = PClass::FindClass(static_cast<FIntermissionActionCast*>(desc)->mCastClass); if (mClass != NULL) mDefaults = GetDefaultByType(mClass); else { mDefaults = NULL; caststate = NULL; return; } mCastSounds.Resize(static_cast<FIntermissionActionCast*>(desc)->mCastSounds.Size()); for (unsigned i=0; i < mCastSounds.Size(); i++) { mCastSounds[i].mSequence = static_cast<FIntermissionActionCast*>(desc)->mCastSounds[i].mSequence; mCastSounds[i].mIndex = static_cast<FIntermissionActionCast*>(desc)->mCastSounds[i].mIndex; mCastSounds[i].mSound = static_cast<FIntermissionActionCast*>(desc)->mCastSounds[i].mSound; } caststate = mDefaults->SeeState; if (mClass->IsDescendantOf(RUNTIME_CLASS(APlayerPawn))) { advplayerstate = mDefaults->MissileState; casttranslation = translationtables[TRANSLATION_Players][consoleplayer]; } else { advplayerstate = NULL; casttranslation = NULL; if (mDefaults->Translation != 0) { casttranslation = translationtables[GetTranslationType(mDefaults->Translation)] [GetTranslationIndex(mDefaults->Translation)]; } } castdeath = false; castframes = 0; castonmelee = 0; castattacking = false; if (mDefaults->SeeSound) { S_Sound (CHAN_VOICE | CHAN_UI, mDefaults->SeeSound, 1, ATTN_NONE); } }
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnFly) { FSoundID sound; ACTION_PARAM_START(1); ACTION_PARAM_CLASS(spawntype, 0); if (spawntype != NULL) { sound = GetDefaultByType(spawntype)->SeeSound; } else { spawntype = PClass::FindClass ("SpawnFire"); sound = "brain/spawn"; } SpawnFly(self, spawntype, sound); }
bool AWeaponPiece::TryPickupRestricted (AActor *&toucher) { // Wrong class, but try to pick up for ammo if (ShouldStay()) { // Can't pick up weapons for other classes in coop netplay return false; } AWeapon * Defaults=(AWeapon*)GetDefaultByType(WeaponClass); bool gaveSome = !!(toucher->GiveAmmo (Defaults->AmmoType1, Defaults->AmmoGive1) + toucher->GiveAmmo (Defaults->AmmoType2, Defaults->AmmoGive2)); if (gaveSome) { GoAwayAndDie (); } return gaveSome; }
void P_FreeStrifeConversations () { FStrifeDialogueNode *node; while (StrifeDialogues.Pop (node)) { delete node; } for (int i = 0; i < 344; ++i) { if (StrifeTypes[i] != NULL) { GetDefaultByType (StrifeTypes[i])->Conversation = NULL; } } CurNode = NULL; PrevNode = NULL; }
static void FinishThingdef() { int errorcount = StateParams.ResolveAll(); for (unsigned i = 0;i < PClass::m_Types.Size(); i++) { PClass * ti = PClass::m_Types[i]; // Skip non-actors if (!ti->IsDescendantOf(RUNTIME_CLASS(AActor))) continue; if (ti->Size == (unsigned)-1) { Printf("Class %s referenced but not defined\n", ti->TypeName.GetChars()); errorcount++; continue; } AActor *def = GetDefaultByType(ti); if (!def) { Printf("No ActorInfo defined for class '%s'\n", ti->TypeName.GetChars()); errorcount++; continue; } } if (errorcount > 0) { I_Error("%d errors during actor postprocessing", errorcount); } // Since these are defined in DECORATE now the table has to be initialized here. for(int i=0;i<31;i++) { char fmt[20]; mysnprintf(fmt, countof(fmt), "QuestItem%d", i+1); QuestItemClasses[i] = PClass::FindClass(fmt); } }
void FWeaponSlots::AddExtraWeapons() { unsigned int i; // Set fractional positions for current weapons. for (i = 0; i < NUM_WEAPON_SLOTS; ++i) { Slots[i].SetInitialPositions(); } // Append extra weapons to the slots. for (unsigned int i = 0; i < PClass::m_Types.Size(); ++i) { PClass *cls = PClass::m_Types[i]; if (cls->ActorInfo != NULL && (cls->ActorInfo->GameFilter == GAME_Any || (cls->ActorInfo->GameFilter & gameinfo.gametype)) && cls->ActorInfo->Replacement == NULL && // Replaced weapons don't get slotted. cls->IsDescendantOf(RUNTIME_CLASS(AWeapon)) && !(static_cast<AWeapon*>(GetDefaultByType(cls))->WeaponFlags & WIF_POWERED_UP) && !LocateWeapon(cls, NULL, NULL) // Don't duplicate it if it's already present. ) { int slot = cls->Meta.GetMetaInt(AWMETA_SlotNumber, -1); if ((unsigned)slot < NUM_WEAPON_SLOTS) { fixed_t position = cls->Meta.GetMetaFixed(AWMETA_SlotPriority, INT_MAX); FWeaponSlot::WeaponInfo info = { cls, position }; Slots[slot].Weapons.Push(info); } } } // Now resort every slot to put the new weapons in their proper places. for (i = 0; i < NUM_WEAPON_SLOTS; ++i) { Slots[i].Sort(); } }
FSpriteModelFrame * gl_FindModelFrame(const PClass * ti, int sprite, int frame, bool dropped) { if (GetDefaultByType(ti)->hasmodel) { FSpriteModelFrame smf; memset(&smf, 0, sizeof(smf)); smf.type=ti; smf.sprite=sprite; smf.frame=frame; int hash = SpriteModelHash[ModelFrameHash(&smf) % SpriteModelFrames.Size()]; while (hash>=0) { FSpriteModelFrame * smff = &SpriteModelFrames[hash]; if (smff->type==ti && smff->sprite==sprite && smff->frame==frame) return smff; hash=smff->hashnext; } } // Check for voxel replacements if (r_drawvoxels) { spritedef_t *sprdef = &sprites[sprite]; if (frame < sprdef->numframes) { spriteframe_t *sprframe = &SpriteFrames[sprdef->spriteframes + frame]; if (sprframe->Voxel != nullptr) { int index = sprframe->Voxel->VoxeldefIndex; if (dropped && sprframe->Voxel->DroppedSpin !=sprframe->Voxel->PlacedSpin) index++; return &SpriteModelFrames[index]; } } } return nullptr; }
static void AddAmmoToList(AWeapon * weapdef) { for(int i=0; i<2;i++) { PClassAmmo * ti = i==0? weapdef->AmmoType1 : weapdef->AmmoType2; if (ti) { AAmmo * ammodef=(AAmmo*)GetDefaultByType(ti); if (ammodef && !(ammodef->ItemFlags&IF_INVBAR)) { unsigned int j; for(j=0;j<orderedammos.Size();j++) { if (ti == orderedammos[j]) break; } if (j==orderedammos.Size()) orderedammos.Push(ti); } } } }
FSpriteModelFrame * gl_FindModelFrame(const PClass * ti, int sprite, int frame) { if (GetDefaultByType(ti)->hasmodel) { FSpriteModelFrame smf; memset(&smf, 0, sizeof(smf)); smf.type=ti; smf.sprite=sprite; smf.frame=frame; int hash = SpriteModelHash[ModelFrameHash(&smf) % SpriteModelFrames.Size()]; while (hash>=0) { FSpriteModelFrame * smff = &SpriteModelFrames[hash]; if (smff->type==ti && smff->sprite==sprite && smff->frame==frame) return smff; hash=smff->hashnext; } } return NULL; }
void LoadActors() { cycle_t timer; timer.Reset(); timer.Clock(); FScriptPosition::ResetErrorCounter(); InitThingdef(); FScriptPosition::StrictErrors = true; ParseScripts(); FScriptPosition::StrictErrors = false; ParseAllDecorate(); FunctionBuildList.Build(); if (FScriptPosition::ErrorCounter > 0) { I_Error("%d errors while parsing DECORATE scripts", FScriptPosition::ErrorCounter); } FScriptPosition::ResetErrorCounter(); for (int i = PClassActor::AllActorClasses.Size() - 1; i >= 0; i--) { auto ti = PClassActor::AllActorClasses[i]; if (ti->Size == TentativeClass) { if (ti->ObjectFlags & OF_Transient) { Printf(TEXTCOLOR_ORANGE "Class %s referenced but not defined\n", ti->TypeName.GetChars()); FScriptPosition::WarnCounter++; DObject::StaticPointerSubstitution(ti, nullptr); PClassActor::AllActorClasses.Delete(i); } else { Printf(TEXTCOLOR_RED "Class %s referenced but not defined\n", ti->TypeName.GetChars()); FScriptPosition::ErrorCounter++; } continue; } if (GetDefaultByType(ti) == nullptr) { Printf(TEXTCOLOR_RED "No ActorInfo defined for class '%s'\n", ti->TypeName.GetChars()); FScriptPosition::ErrorCounter++; continue; } CheckStates(ti); if (ti->bDecorateClass && ti->IsDescendantOf(RUNTIME_CLASS(AStateProvider))) { // either a DECORATE based weapon or CustomInventory. // These are subject to relaxed rules for user variables in states. // Although there is a runtime check for bogus states, let's do a quick analysis if any of the known entry points // hits an unsafe state. If we can find something here it can be handled wuth a compile error rather than a runtime error. CheckForUnsafeStates(ti); } } if (FScriptPosition::ErrorCounter > 0) { I_Error("%d errors during actor postprocessing", FScriptPosition::ErrorCounter); } timer.Unclock(); if (!batchrun) Printf("script parsing took %.2f ms\n", timer.TimeMS()); // Since these are defined in DECORATE now the table has to be initialized here. for (int i = 0; i < 31; i++) { char fmt[20]; mysnprintf(fmt, countof(fmt), "QuestItem%d", i + 1); QuestItemClasses[i] = PClass::FindActor(fmt); } StateSourceLines.Clear(); }
static void DrawConversationMenu () { int i, x, y, linesize; assert (DialogueLines != NULL); assert (CurNode != NULL); if (CurNode == NULL) { M_ClearMenus (); return; } if (ConversationPauseTic < gametic) { menuactive = MENU_On; } if (CurNode->Backdrop >= 0) { screen->DrawTexture (TexMan(CurNode->Backdrop), 0, 0, DTA_320x200, true, TAG_DONE); } x = 16 * screen->GetWidth() / 320; y = 16 * screen->GetHeight() / 200; linesize = 10 * CleanYfac; // Dim the screen behind the dialogue (but only if there is no backdrop). if (CurNode->Backdrop <= 0) { for (i = 0; DialogueLines[i].width != -1; ++i) { } screen->Dim (0, 0.45f, 14 * screen->GetWidth() / 320, 13 * screen->GetHeight() / 200, 308 * screen->GetWidth() / 320 - 14 * screen->GetWidth () / 320, CurNode->SpeakerName == NULL ? linesize * i + 6 * CleanYfac : linesize * i + 6 * CleanYfac + linesize * 3/2); } // Dim the screen behind the PC's choices. screen->Dim (0, 0.45f, (24-160) * CleanXfac + screen->GetWidth()/2, (ConversationMenu.y - 2 - 100) * CleanYfac + screen->GetHeight()/2, 272 * CleanXfac, MIN(ConversationMenu.numitems * (gameinfo.gametype & GAME_Raven ? 9 : 8) + 4, 200 - ConversationMenu.y) * CleanYfac); if (CurNode->SpeakerName != NULL) { screen->DrawText (CR_WHITE, x, y, CurNode->SpeakerName, DTA_CleanNoMove, true, TAG_DONE); y += linesize * 3 / 2; } x = 24 * screen->GetWidth() / 320; for (i = 0; DialogueLines[i].width >= 0; ++i) { screen->DrawText (CR_UNTRANSLATED, x, y, DialogueLines[i].string, DTA_CleanNoMove, true, TAG_DONE); y += linesize; } if (ShowGold) { AInventory *coin = ConversationPC->FindInventory (RUNTIME_CLASS(ACoin)); char goldstr[32]; sprintf (goldstr, "%d", coin != NULL ? coin->Amount : 0); screen->DrawText (CR_GRAY, 21, 191, goldstr, DTA_320x200, true, DTA_FillColor, 0, DTA_Alpha, HR_SHADOW, TAG_DONE); screen->DrawTexture (TexMan(((AInventory *)GetDefaultByType (RUNTIME_CLASS(ACoin)))->Icon), 3, 190, DTA_320x200, true, DTA_FillColor, 0, DTA_Alpha, HR_SHADOW, TAG_DONE); screen->DrawText (CR_GRAY, 20, 190, goldstr, DTA_320x200, true, TAG_DONE); screen->DrawTexture (TexMan(((AInventory *)GetDefaultByType (RUNTIME_CLASS(ACoin)))->Icon), 2, 189, DTA_320x200, true, TAG_DONE); } }
static FStrifeDialogueNode *ReadTeaserNode (FWadLump *lump, DWORD &prevSpeakerType) { FStrifeDialogueNode *node; TeaserSpeech speech; char fullsound[16]; const TypeInfo *type; int j; node = new FStrifeDialogueNode; lump->Read (&speech, sizeof(speech)); // Byte swap all the ints in the original data speech.SpeakerType = LONG(speech.SpeakerType); speech.DropType = LONG(speech.DropType); // Assign the first instance of a conversation as the default for its // actor, so newly spawned actors will use this conversation by default. type = GetStrifeType (speech.SpeakerType); node->SpeakerType = type; if (prevSpeakerType != speech.SpeakerType) { if (type != NULL) { GetDefaultByType (type)->Conversation = node; } prevSpeakerType = speech.SpeakerType; } // Convert the rest of the data to our own internal format. node->Dialogue = ncopystring (speech.Dialogue); // The Teaser version doesn't have portraits. node->Backdrop = -1; // The speaker's voice for this node, if any. if (speech.VoiceNumber != 0) { sprintf (fullsound, "svox/voc%lu", speech.VoiceNumber); node->SpeakerVoice = S_FindSound (fullsound); } else { node->SpeakerVoice = 0; } // The speaker's name, if any. speech.Name[16] = 0; node->SpeakerName = ncopystring (speech.Name); // The item the speaker should drop when killed. node->DropType = GetStrifeType (speech.DropType); // Items you need to have to make the speaker use a different node. for (j = 0; j < 3; ++j) { node->ItemCheck[j] = NULL; } node->ItemCheckNode = 0; node->Children = NULL; ParseReplies (&node->Children, &speech.Responses[0]); return node; }
void gl_InitModels() { int Lump, lastLump; FString path; int index, surface; int i; FSpriteModelFrame smf; lastLump = 0; for(unsigned i=0;i<Models.Size();i++) { delete Models[i]; } Models.Clear(); SpriteModelFrames.Clear(); DeleteModelHash(); // First, create models for each voxel for (unsigned i = 0; i < Voxels.Size(); i++) { FVoxelModel *md = new FVoxelModel(Voxels[i], false); Voxels[i]->VoxelIndex = Models.Push(md); } // now create GL model frames for the voxeldefs for (unsigned i = 0; i < VoxelDefs.Size(); i++) { FVoxelModel *md = (FVoxelModel*)Models[VoxelDefs[i]->Voxel->VoxelIndex]; memset(&smf, 0, sizeof(smf)); smf.modelIDs[1] = smf.modelIDs[2] = smf.modelIDs[3] = -1; smf.modelIDs[0] = VoxelDefs[i]->Voxel->VoxelIndex; smf.skinIDs[0] = md->GetPaletteTexture(); smf.xscale = smf.yscale = smf.zscale = VoxelDefs[i]->Scale; smf.angleoffset = VoxelDefs[i]->AngleOffset.Degrees; if (VoxelDefs[i]->PlacedSpin != 0) { smf.yrotate = 1.f; smf.rotationSpeed = VoxelDefs[i]->PlacedSpin / 55.55f; smf.flags |= MDL_ROTATING; } VoxelDefs[i]->VoxeldefIndex = SpriteModelFrames.Push(smf); if (VoxelDefs[i]->PlacedSpin != VoxelDefs[i]->DroppedSpin) { if (VoxelDefs[i]->DroppedSpin != 0) { smf.yrotate = 1.f; smf.rotationSpeed = VoxelDefs[i]->DroppedSpin / 55.55f; smf.flags |= MDL_ROTATING; } else { smf.yrotate = 0; smf.rotationSpeed = 0; smf.flags &= ~MDL_ROTATING; } SpriteModelFrames.Push(smf); } } memset(&smf, 0, sizeof(smf)); smf.modelIDs[0] = smf.modelIDs[1] = smf.modelIDs[2] = smf.modelIDs[3] = -1; while ((Lump = Wads.FindLump("MODELDEF", &lastLump)) != -1) { FScanner sc(Lump); while (sc.GetString()) { if (sc.Compare("model")) { path = ""; sc.MustGetString(); memset(&smf, 0, sizeof(smf)); smf.modelIDs[1] = smf.modelIDs[2] = smf.modelIDs[3] = -1; smf.xscale=smf.yscale=smf.zscale=1.f; smf.type = PClass::FindClass(sc.String); if (!smf.type || smf.type->Defaults == nullptr) { sc.ScriptError("MODELDEF: Unknown actor type '%s'\n", sc.String); } sc.MustGetStringName("{"); while (!sc.CheckString("}")) { sc.MustGetString(); if (sc.Compare("path")) { sc.MustGetString(); FixPathSeperator(sc.String); path = sc.String; if (path[(int)path.Len()-1]!='/') path+='/'; } else if (sc.Compare("model")) { sc.MustGetNumber(); index = sc.Number; if (index < 0 || index >= MAX_MODELS_PER_FRAME) { sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars()); } sc.MustGetString(); FixPathSeperator(sc.String); smf.modelIDs[index] = FindModel(path.GetChars(), sc.String); if (smf.modelIDs[index] == -1) { Printf("%s: model not found in %s\n", sc.String, path.GetChars()); } } else if (sc.Compare("scale")) { sc.MustGetFloat(); smf.xscale = sc.Float; sc.MustGetFloat(); smf.yscale = sc.Float; sc.MustGetFloat(); smf.zscale = sc.Float; } // [BB] Added zoffset reading. // Now it must be considered deprecated. else if (sc.Compare("zoffset")) { sc.MustGetFloat(); smf.zoffset=sc.Float; } // Offset reading. else if (sc.Compare("offset")) { sc.MustGetFloat(); smf.xoffset = sc.Float; sc.MustGetFloat(); smf.yoffset = sc.Float; sc.MustGetFloat(); smf.zoffset = sc.Float; } // angleoffset, pitchoffset and rolloffset reading. else if (sc.Compare("angleoffset")) { sc.MustGetFloat(); smf.angleoffset = sc.Float; } else if (sc.Compare("pitchoffset")) { sc.MustGetFloat(); smf.pitchoffset = sc.Float; } else if (sc.Compare("rolloffset")) { sc.MustGetFloat(); smf.rolloffset = sc.Float; } // [BB] Added model flags reading. else if (sc.Compare("ignoretranslation")) { smf.flags |= MDL_IGNORETRANSLATION; } else if (sc.Compare("pitchfrommomentum")) { smf.flags |= MDL_PITCHFROMMOMENTUM; } else if (sc.Compare("inheritactorpitch")) { smf.flags |= MDL_USEACTORPITCH | MDL_BADROTATION; } else if (sc.Compare("inheritactorroll")) { smf.flags |= MDL_USEACTORROLL; } else if (sc.Compare("useactorpitch")) { smf.flags |= MDL_USEACTORPITCH; } else if (sc.Compare("useactorroll")) { smf.flags |= MDL_USEACTORROLL; } else if (sc.Compare("rotating")) { smf.flags |= MDL_ROTATING; smf.xrotate = 0.; smf.yrotate = 1.; smf.zrotate = 0.; smf.rotationCenterX = 0.; smf.rotationCenterY = 0.; smf.rotationCenterZ = 0.; smf.rotationSpeed = 1.; } else if (sc.Compare("rotation-speed")) { sc.MustGetFloat(); smf.rotationSpeed = sc.Float; } else if (sc.Compare("rotation-vector")) { sc.MustGetFloat(); smf.xrotate = sc.Float; sc.MustGetFloat(); smf.yrotate = sc.Float; sc.MustGetFloat(); smf.zrotate = sc.Float; } else if (sc.Compare("rotation-center")) { sc.MustGetFloat(); smf.rotationCenterX = sc.Float; sc.MustGetFloat(); smf.rotationCenterY = sc.Float; sc.MustGetFloat(); smf.rotationCenterZ = sc.Float; } else if (sc.Compare("interpolatedoubledframes")) { smf.flags |= MDL_INTERPOLATEDOUBLEDFRAMES; } else if (sc.Compare("nointerpolation")) { smf.flags |= MDL_NOINTERPOLATION; } else if (sc.Compare("skin")) { sc.MustGetNumber(); index=sc.Number; if (index<0 || index>=MAX_MODELS_PER_FRAME) { sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars()); } sc.MustGetString(); FixPathSeperator(sc.String); if (sc.Compare("")) { smf.skinIDs[index]=FNullTextureID(); } else { smf.skinIDs[index] = LoadSkin(path.GetChars(), sc.String); if (!smf.skinIDs[index].isValid()) { Printf("Skin '%s' not found in '%s'\n", sc.String, smf.type->TypeName.GetChars()); } } } else if (sc.Compare("surfaceskin")) { sc.MustGetNumber(); index = sc.Number; sc.MustGetNumber(); surface = sc.Number; if (index<0 || index >= MAX_MODELS_PER_FRAME) { sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars()); } if (surface<0 || surface >= MD3_MAX_SURFACES) { sc.ScriptError("Invalid MD3 Surface %d in %s", MD3_MAX_SURFACES, smf.type->TypeName.GetChars()); } sc.MustGetString(); FixPathSeperator(sc.String); if (sc.Compare("")) { smf.surfaceskinIDs[index][surface] = FNullTextureID(); } else { smf.surfaceskinIDs[index][surface] = LoadSkin(path.GetChars(), sc.String); if (!smf.surfaceskinIDs[index][surface].isValid()) { Printf("Surface Skin '%s' not found in '%s'\n", sc.String, smf.type->TypeName.GetChars()); } } } else if (sc.Compare("frameindex") || sc.Compare("frame")) { bool isframe=!!sc.Compare("frame"); sc.MustGetString(); smf.sprite = -1; for (i = 0; i < (int)sprites.Size (); ++i) { if (strnicmp (sprites[i].name, sc.String, 4) == 0) { if (sprites[i].numframes==0) { //sc.ScriptError("Sprite %s has no frames", sc.String); } smf.sprite = i; break; } } if (smf.sprite==-1) { sc.ScriptError("Unknown sprite %s in model definition for %s", sc.String, smf.type->TypeName.GetChars()); } sc.MustGetString(); FString framechars = sc.String; sc.MustGetNumber(); index=sc.Number; if (index<0 || index>=MAX_MODELS_PER_FRAME) { sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars()); } if (isframe) { sc.MustGetString(); if (smf.modelIDs[index] != -1) { FModel *model = Models[smf.modelIDs[index]]; smf.modelframes[index] = model->FindFrame(sc.String); if (smf.modelframes[index]==-1) sc.ScriptError("Unknown frame '%s' in %s", sc.String, smf.type->TypeName.GetChars()); } else smf.modelframes[index] = -1; } else { sc.MustGetNumber(); smf.modelframes[index] = sc.Number; } for(i=0; framechars[i]>0; i++) { char map[29]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; int c = toupper(framechars[i])-'A'; if (c<0 || c>=29) { sc.ScriptError("Invalid frame character %c found", c+'A'); } if (map[c]) continue; smf.frame=c; SpriteModelFrames.Push(smf); GetDefaultByType(smf.type)->hasmodel = true; map[c]=1; } } else { sc.ScriptMessage("Unrecognized string \"%s\"", sc.String); } } } } } // create a hash table for quick access SpriteModelHash = new int[SpriteModelFrames.Size ()]; atterm(DeleteModelHash); memset(SpriteModelHash, 0xff, SpriteModelFrames.Size () * sizeof(int)); for (i = 0; i < (int)SpriteModelFrames.Size (); i++) { int j = ModelFrameHash(&SpriteModelFrames[i]) % SpriteModelFrames.Size (); SpriteModelFrames[i].hashnext = SpriteModelHash[j]; SpriteModelHash[j]=i; } }
// set the bot specific weapon information // This is intentionally not in the weapon definition anymore. void InitBotStuff() { static struct BotInit { const char *type; int movecombatdist; int weaponflags; const char *projectile; } botinits[] = { { "Pistol", 25000000, 0, NULL }, { "Shotgun", 24000000, 0, NULL }, { "SuperShotgun", 15000000, 0, NULL }, { "Chaingun", 27000000, 0, NULL }, { "RocketLauncher", 18350080, WIF_BOT_REACTION_SKILL_THING|WIF_BOT_EXPLOSIVE, "Rocket" }, { "PlasmaRifle", 27000000, 0, "PlasmaBall" }, { "BFG9000", 10000000, WIF_BOT_REACTION_SKILL_THING|WIF_BOT_BFG, "BFGBall" }, { "GoldWand", 25000000, 0, NULL }, { "GoldWandPowered", 25000000, 0, NULL }, { "Crossbow", 24000000, 0, "CrossbowFX1" }, { "CrossbowPowered", 24000000, 0, "CrossbowFX2" }, { "Blaster", 27000000, 0, NULL }, { "BlasterPowered", 27000000, 0, "BlasterFX1" }, { "SkullRod", 27000000, 0, "HornRodFX1" }, { "SkullRodPowered", 27000000, 0, "HornRodFX2" }, { "PhoenixRod", 18350080, WIF_BOT_REACTION_SKILL_THING|WIF_BOT_EXPLOSIVE, "PhoenixFX1" }, { "Mace", 27000000, WIF_BOT_REACTION_SKILL_THING, "MaceFX2" }, { "MacePowered", 27000000, WIF_BOT_REACTION_SKILL_THING|WIF_BOT_EXPLOSIVE, "MaceFX4" }, { "FWeapHammer", 22000000, 0, "HammerMissile" }, { "FWeapQuietus", 20000000, 0, "FSwordMissile" }, { "CWeapStaff", 25000000, 0, "CStaffMissile" }, { "CWeapFlane", 27000000, 0, "CFlameMissile" }, { "MWeapWand", 25000000, 0, "MageWandMissile" }, { "CWeapWraithverge", 22000000, 0, "HolyMissile" }, { "MWeapFrost", 19000000, 0, "FrostMissile" }, { "MWeapLightning", 23000000, 0, "LightningFloor" }, { "MWeapBloodscourge", 20000000, 0, "MageStaffFX2" }, { "StrifeCrossbow", 24000000, 0, "ElectricBolt" }, { "StrifeCrossbow2", 24000000, 0, "PoisonBolt" }, { "AssaultGun", 27000000, 0, NULL }, { "MiniMissileLauncher", 18350080, WIF_BOT_REACTION_SKILL_THING|WIF_BOT_EXPLOSIVE, "MiniMissile" }, { "FlameThrower", 24000000, 0, "FlameMissile" }, { "Mauler", 15000000, 0, NULL }, { "Mauler2", 10000000, 0, "MaulerTorpedo" }, { "StrifeGrenadeLauncher", 18350080, WIF_BOT_REACTION_SKILL_THING|WIF_BOT_EXPLOSIVE, "HEGrenade" }, { "StrifeGrenadeLauncher2", 18350080, WIF_BOT_REACTION_SKILL_THING|WIF_BOT_EXPLOSIVE, "PhosphorousGrenade" }, }; for(unsigned i=0;i<sizeof(botinits)/sizeof(botinits[0]);i++) { const PClass *cls = PClass::FindClass(botinits[i].type); if (cls != NULL && cls->IsDescendantOf(RUNTIME_CLASS(AWeapon))) { AWeapon *w = (AWeapon*)GetDefaultByType(cls); if (w != NULL) { w->MoveCombatDist = botinits[i].movecombatdist/65536.; w->WeaponFlags |= botinits[i].weaponflags; w->ProjectileType = PClass::FindActor(botinits[i].projectile); } } } static const char *warnbotmissiles[] = { "PlasmaBall", "Ripper", "HornRodFX1" }; for(unsigned i=0;i<countof(warnbotmissiles);i++) { AActor *a = GetDefaultByName (warnbotmissiles[i]); if (a != NULL) { a->flags3|=MF3_WARNBOT; } } }
static int DrawAmmo(player_t *CPlayer, int x, int y) { int i,j,k; char buf[256]; AInventory *inv; AWeapon *wi=CPlayer->ReadyWeapon; orderedammos.Clear(); if (0 == hud_showammo) { // Show ammo for current weapon if any if (wi) AddAmmoToList(wi); } else { // Order ammo by use of weapons in the weapon slots for (k = 0; k < NUM_WEAPON_SLOTS; k++) for(j = 0; j < CPlayer->weapons.Slots[k].Size(); j++) { PClassActor *weap = CPlayer->weapons.Slots[k].GetWeapon(j); if (weap) { // Show ammo for available weapons if hud_showammo CVAR is 1 // or show ammo for all weapons if hud_showammo is greater than 1 if (hud_showammo > 1 || CPlayer->mo->FindInventory(weap)) { AddAmmoToList((AWeapon*)GetDefaultByType(weap)); } } } // Now check for the remaining weapons that are in the inventory but not in the weapon slots for(inv=CPlayer->mo->Inventory;inv;inv=inv->Inventory) { if (inv->IsKindOf(RUNTIME_CLASS(AWeapon))) { AddAmmoToList((AWeapon*)inv); } } } // ok, we got all ammo types. Now draw the list back to front (bottom to top) int def_width = ConFont->StringWidth("000/000"); x-=def_width; int yadd = ConFont->GetHeight(); for(i=orderedammos.Size()-1;i>=0;i--) { PClassAmmo * type = orderedammos[i]; AAmmo * ammoitem = (AAmmo*)CPlayer->mo->FindInventory(type); AAmmo * inv = ammoitem? ammoitem : (AAmmo*)GetDefaultByType(orderedammos[i]); FTextureID AltIcon = GetHUDIcon(type); FTextureID icon = !AltIcon.isNull()? AltIcon : inv->Icon; if (!icon.isValid()) continue; int trans= (wi && (type==wi->AmmoType1 || type==wi->AmmoType2)) ? 0xc000:0x6000; int maxammo = inv->MaxAmount; int ammo = ammoitem? ammoitem->Amount : 0; mysnprintf(buf, countof(buf), "%3d/%3d", ammo, maxammo); int tex_width= clamp<int>(ConFont->StringWidth(buf)-def_width, 0, 1000); int fontcolor=( !maxammo ? CR_GRAY : ammo < ( (maxammo * hud_ammo_red) / 100) ? CR_RED : ammo < ( (maxammo * hud_ammo_yellow) / 100) ? CR_GOLD : CR_GREEN ); DrawHudText(ConFont, fontcolor, buf, x-tex_width, y+yadd, trans); DrawImageToBox(TexMan[icon], x-20, y, 16, 8, trans); y-=10; } return y; }