From 33ef74cbcbbd7e140bbf242471d602f47d9c4c92 Mon Sep 17 00:00:00 2001 From: ketmar Date: Mon, 21 May 2012 06:04:56 +0300 Subject: [PATCH] finished adding content from CLIVAN; not tested yet --- Script/char.dat | 62 + Script/char_10.dat | 1 - Script/char_11.dat | 65 + Script/char_13.dat | 328 +++ Script/char_14.dat | 317 +++ Script/define.dat | 11 +- Script/dungeon.dat | 5 +- Script/dungeons/darkforest.dat | 2141 ++++++++++++++++++++ Script/dungeons/dragontower.dat | 74 + Script/dungeons/mondedr.dat | 117 +- Script/dungeons/muntuo.dat | 2 - Script/dungeons/xinrochtomb.dat | 74 + Script/item_11.dat | 129 ++ src/game/char.cpp | 55 + src/game/char.h | 4 + src/game/confdef.h | 5 + src/game/game.cpp | 17 +- src/game/game.h | 6 + src/game/gears/meleeweapon_taiaha.cpp | 369 ++-- src/game/humans/humanoid_UTFAOfficial.cpp | 7 + src/game/humans/humanoid_ennerbeast.cpp | 4 + src/game/humans/humanoid_forestman.cpp | 26 + src/game/humans/humanoid_kabouter.cpp | 125 ++ src/game/humans/humanoid_morbe.cpp | 124 ++ src/game/humans/humanoid_regii.cpp | 58 + src/game/humans/humanoid_uldra.cpp | 130 ++ src/game/item.cpp | 1 + src/game/item.h | 3 + src/game/items/0list.cpp | 15 + src/game/items/holybook_celestialmonograph.cpp | 5 +- src/game/items/item_holymango.cpp | 91 + src/game/items/item_locationmap.cpp | 30 + src/game/items/item_mango.cpp | 2 + src/game/items/locationmap_maptotombofxinroch.cpp | 31 + src/game/items/materialcontainer_can.cpp | 111 +- src/game/items/materialcontainer_cauldron.cpp | 48 + src/game/items/materialcontainer_kleinbottle.cpp | 49 + src/game/items/scroll_scrolloffireballs.cpp | 78 + src/game/nonhumans/0list.cpp | 9 + src/game/nonhumans/canine_firefox.cpp | 48 + src/game/nonhumans/largecreature_anvitas.cpp | 22 + .../nonhumans/largecreature_genefourxvesana.cpp | 143 ++ src/game/nonhumans/largecreature_haastseagle.cpp | 21 + src/game/nonhumans/nonhumanoid_bluedragon.cpp | 5 + src/game/nonhumans/nonhumanoid_fruitbat.cpp | 52 + .../nonhumanoid_okapi.cpp} | 2 +- src/game/nonhumans/nonhumanoid_reddragon.cpp | 5 + src/game/nonhumans/nonhumanoid_thunderbird.cpp | 39 + src/game/worldmap.cpp | 26 +- src/game/wterrains/owterrains/0list.cpp | 3 + .../wterrains/owterrains/owterrain_darkforest.cpp | 19 + .../wterrains/owterrains/owterrain_dragontower.cpp | 19 + .../wterrains/owterrains/owterrain_xinrochtomb.cpp | 19 + 53 files changed, 4853 insertions(+), 299 deletions(-) create mode 100644 Script/dungeons/darkforest.dat create mode 100644 Script/dungeons/dragontower.dat create mode 100644 Script/dungeons/xinrochtomb.dat rewrite src/game/gears/meleeweapon_taiaha.cpp (65%) create mode 100644 src/game/humans/humanoid_UTFAOfficial.cpp create mode 100644 src/game/humans/humanoid_forestman.cpp create mode 100644 src/game/humans/humanoid_kabouter.cpp create mode 100644 src/game/humans/humanoid_morbe.cpp create mode 100644 src/game/humans/humanoid_regii.cpp create mode 100644 src/game/humans/humanoid_uldra.cpp create mode 100644 src/game/items/item_holymango.cpp create mode 100644 src/game/items/item_locationmap.cpp create mode 100644 src/game/items/locationmap_maptotombofxinroch.cpp rewrite src/game/items/materialcontainer_can.cpp (86%) create mode 100644 src/game/items/materialcontainer_cauldron.cpp create mode 100644 src/game/items/materialcontainer_kleinbottle.cpp create mode 100644 src/game/items/scroll_scrolloffireballs.cpp create mode 100644 src/game/nonhumans/canine_firefox.cpp create mode 100644 src/game/nonhumans/largecreature_anvitas.cpp create mode 100644 src/game/nonhumans/largecreature_genefourxvesana.cpp create mode 100644 src/game/nonhumans/largecreature_haastseagle.cpp create mode 100644 src/game/nonhumans/nonhumanoid_bluedragon.cpp create mode 100644 src/game/nonhumans/nonhumanoid_fruitbat.cpp copy src/game/{items/item_mango.cpp => nonhumans/nonhumanoid_okapi.cpp} (51%) create mode 100644 src/game/nonhumans/nonhumanoid_reddragon.cpp create mode 100644 src/game/nonhumans/nonhumanoid_thunderbird.cpp create mode 100644 src/game/wterrains/owterrains/owterrain_darkforest.cpp create mode 100644 src/game/wterrains/owterrains/owterrain_dragontower.cpp create mode 100644 src/game/wterrains/owterrains/owterrain_xinrochtomb.cpp diff --git a/Script/char.dat b/Script/char.dat index 40d4999..ac5d40e 100644 --- a/Script/char.dat +++ b/Script/char.dat @@ -2456,6 +2456,31 @@ housewife "\"Petrus's wives are so arrogant towards us working class ones. Grr...\"", "\"If you men only knew!\""; } + + Config MONDEDR; + { + LegMainColor = rgb16(0, 80, 180); + Cloak = CLOTH cloak; + Inventory == lantern; + FriendlyReplies = + { + 2, + "\"If Mondedr wasn't on Petrus's wanted list it wouldn't be so dark all the time.\"", + "\"I heard the shopkeeper in town is a dirty one. I'd rather have the previous owner of the shop.\""; + } + } + + Config DARK_FOREST; + { + LegMainColor = rgb16(120, 120, 120); + Cloak = CLOTH cloak; + FriendlyReplies = + { + 2, + "\"Gah! Put me back in the jail cell! I don't want to end up with those ghastly UTFA floosies.\"", + "\"Just hurry and get me to Attnam already. Has that jeweller's shop opened up there yet?\""; + } + } } femaleslave @@ -4850,6 +4875,36 @@ hedgehog AttachedGod = SILVA; AutomaticallySeen = true; CanOpen = false; + + Config SONIC; + { + DefaultArmStrength = 20; + DefaultAgility = 65; + DefaultEndurance = 30; + DefaultPerception = 25; + DefaultIntelligence = 10; + DefaultWisdom = 10; + DefaultCharisma = 50; + Adjective = 0; + DefaultName = "Sonic"; + Alias == "Sonic"; + IsUnique = true; + SkinColor = rgb16(50, 50, 180); + FriendlyReplies = { + 11, + "\"Way past cool!\"", + "\"I'm waaaiiitiiiinnng. \"", + "\"Up, over, and gone!.\""; + "\"Gotta juice and loose.\""; + "\"Let's go slo-mo!\""; + "\"'scuse me while I chunk my breakfeast...\""; + "\"Asta la vista!.\""; + "\"Gotta speed jeeves.\""; + "\"Let's do it to it.\""; + "\"It's juice and jam time.\""; + "\"Bummer majores!\""; + } + } } bunny @@ -4994,6 +5049,13 @@ hattifattener Alias == "Hattivatti"; AllowUnconsciousness = false; CanChoke = false; + + Config FLOATIE; + { + Adjective = "levitating"; + MoveType = FLY; + StandVerb = "floating"; + } } necromancer diff --git a/Script/char_10.dat b/Script/char_10.dat index fc928e3..5d04c2f 100644 --- a/Script/char_10.dat +++ b/Script/char_10.dat @@ -365,7 +365,6 @@ doctor Frequency = 2000; } - vampire { DefaultArmStrength = 20; diff --git a/Script/char_11.dat b/Script/char_11.dat index a098bb4..7de8c1f 100644 --- a/Script/char_11.dat +++ b/Script/char_11.dat @@ -185,3 +185,68 @@ Extend priest } } } + +morbe /* high priestess of scabies */ +{ + CanRead = true; + TamingDifficulty = NO_TAMING; + MoveType = WALK|SWIM; + Inventory == potion { Times = 2; SecondaryMaterial = ANTIDOTE_LIQUID; } + DefaultArmStrength = 20; + DefaultLegStrength = 20; + DefaultDexterity = 40; + DefaultAgility = 40; + DefaultEndurance = 10; + DefaultPerception = 30; + DefaultIntelligence = 30; + DefaultWisdom = 45; + DefaultCharisma = 40; + DefaultMana = 40; + TotalVolume = 45000; + TotalSize = 180; + HeadBitmapPos = 112, 256; + TorsoBitmapPos = 32, 160; + ArmBitmapPos = 64, 208; + LegBitmapPos = 16, 160; + SkinColor = rgb16(160, 200, 160); + HairColor = rgb16(160, 48, 48); + ClothColor = rgb16(160, 60, 160); + EyeColor = rgb16(180, 0, 160); + BaseEmitation = rgb16(125, 160, 125); + AttachedGod = SCABIES; + NameSingular = "high priestess"; + PostFix = "of Scabies"; + Sex = FEMALE; + Cloak = HESSIAN_CLOTH cloak; + RightWielded = RUBY daggerofvenom { Enchantment = 4; } + KnownCWeaponSkills == SMALL_SWORDS; + CWeaponSkillHits == 500; + RightSWeaponSkillHits = 200; + /* Replies overridden */ + AutomaticallySeen = true; + IsNameable = false; + IsUnique = true; + IsPolymorphable = false; + Amulet = amulet(AMULET_OF_VANITY); + BodyArmor = RUBY bodyarmor(PLATE_MAIL) { Enchantment = 4; } + Cloak = DAEMON_FLESH cloak(CLOAK_OF_ELECTRICITY_RESISTANCE) { Enchantment = 4; } + Belt = ELPURI_FLESH belt { Enchantment = 4; } + RightGauntlet = DRAGON_HIDE gauntlet(GAUNTLET_OF_STRENGTH) { Enchantment = 4; } + RightRing = ring(RING_OF_FIRE_RESISTANCE); + LeftRing = ring(RING_OF_POISON_RESISTANCE); + RightBoot = SPIDER_SILK boot(BOOT_OF_AGILITY) { Enchantment = 4; } + PanicLevel = 0; + CanBeCloned = false; + DefaultName = "Morbe"; + DeathMessage = "The high priestess vanishes from the bowels of Valpurus."; + BodyPartsDisappearWhenSevered = true; + CanBeConfused = false; + EnergyResistance = 50; + IsImmuneToLeprosy = true; + IsImmuneToItemTeleport = true; + AllowUnconsciousness = false; + DisplacePriority = 10; + UndeadVersions = false; + IsImmuneToWhipOfThievery = true; + IsExtraFragile = true; +} diff --git a/Script/char_13.dat b/Script/char_13.dat index 776d69a..76f8612 100644 --- a/Script/char_13.dat +++ b/Script/char_13.dat @@ -79,3 +79,331 @@ grenadierdwarf IsRangedAttacker = true; WhatThrowItemTypesToThrow = THROW_GAS_GRENADE; } + +Extend guard +{ + Config FOREST_SHOP; + { + AttributeBonus = 30; + Helmet = STEEL helmet(FULL_HELMET) { Enchantment = 1; } + BodyArmor = STEEL bodyarmor(PLATE_MAIL) { Enchantment = 1; } + RightWielded = STEEL meleeweapon(HALBERD) { Enchantment = 2; } + LeftWielded = STEEL shield { Enchantment = 2; } + RightRing = ring(RING_OF_INFRA_VISION) { Chance = 50; } + Adjective = "shop"; + CWeaponSkillHits = { 2, 500, 500; } + RightSWeaponSkillHits = 500; + LeftSWeaponSkillHits = 500; + PanicLevel = 15; + ClothColor = rgb16(100, 100, 100); + FriendlyReplies = + { + 5, + "@Dd says gravely: \"You don't have a life. Get it as a shop guard.\"", + "@Dd seems very suspicious. \"Don't even think of stealing anything.\"", + "\"Yes, this is a dangerous place to work, but our boss pays us well.\"", + "\"The troops of the UTFA can barely wield a sword. But we are trained by the laws of the forest, so don't do any rash moves here.\"", + "\"Grah! All I can think about right now is getting back into the dungeon.\""; + } + } +} + +uldra +{ + DefaultArmStrength = 12; + DefaultLegStrength = 10; + DefaultDexterity = 16; + DefaultAgility = 20; + DefaultEndurance = 18; + DefaultPerception = 30; + DefaultIntelligence = 20; + DefaultWisdom = 25; + DefaultCharisma = 40; + DefaultMana = 0; + SkinColor = rgb16(150, 90, 56); + EyeColor = rgb16(192, 192, 192); + HairColor = rgb16(210, 210, 210); + ClothColor = rgb16(124, 124, 124); + CapColor = rgb16(124, 124, 124); + TorsoSpecialColor = rgb16(255, 236, 0); /*belt*/ + BootColor = rgb16(64, 0, 0); + HeadBitmapPos = 112, 704; + TorsoBitmapPos = 48, 704; + ArmBitmapPos = 80, 704; + LegBitmapPos = 16, 704; + TotalVolume = 24000; + TotalSize = 100; + NameSingular = "uldra"; + HostileReplies == "@Dd grins maniaically."; + FriendlyReplies == "@Dd grins."; + CanBeGenerated = true; + Sex = MALE; + RightWielded = MITHRIL OAK_WOOD meleeweapon(SICKLE) { Enchantment = 2; } + KnownCWeaponSkills == SMALL_SWORDS; + CWeaponSkillHits == 30; + RightSWeaponSkillHits = 20; + PanicLevel = 33; + FleshMaterial = ULDRA_FLESH; + DeathMessage = "@Dd dies with a yelp."; + AttachedGod = ATAVUS; + WieldedPosition = 2, 1; + /*Inventory = { 1, wand(WAND_OF_SLOW);}*/ + FireResistance = 20; + ElectricityResistance = 20; + EnergyResistance = 20; + UndeadVersions = false; + CanBeCloned = false; + RightBoot = BLACK_LEATHER boot { Enchantment = 1; } + Helmet = BLACK_LEATHER belt { Enchantment = 1; } + ClassStates = ESP|GAS_IMMUNITY|TELEPORT_CONTROL; + HPRequirementForGeneration = 150; + DayRequirementForGeneration = 5; + DangerModifier = 250; +} + +forestman +{ + CanRead = true; + IsAbstract = true; + AttachedGod = SILVA; + SkinColor = rgb16(200, 110, 70); + DefaultArmStrength = 12; + DefaultLegStrength = 12; + DefaultDexterity = 10; + DefaultAgility = 10; + DefaultEndurance = 12; + DefaultPerception = 20; + DefaultIntelligence = 12; + DefaultWisdom = 12; + DefaultCharisma = 10; + DefaultMana = 10; + TotalVolume = 60000; + TotalSize = 160; + NameSingular = "forest-man"; + HeadBitmapPos = 96, 0; + TorsoBitmapPos = 32, 80; + ArmBitmapPos = 64, 80; + LegBitmapPos = 0, 64; + TamingDifficulty = NO_TAMING; + UndeadVersions = false; + + Config ROVER; + { + AttributeBonus = 0; + Helmet = TIN helmet; + BodyArmor = HARDENED_LEATHER bodyarmor(PLATE_MAIL); + RightWielded = BRONZE meleeweapon(DAGGER) { Enchantment = 2; } + LeftWielded = BIRCH_WOOD shield; + Belt = HARDENED_LEATHER belt; + RightBoot = HARDENED_LEATHER boot; + RightGauntlet = HARDENED_LEATHER gauntlet; + Cloak = HARDENED_LEATHER cloak { Enchantment = 1; } + Adjective = "roving"; + KnownCWeaponSkills = { 2, SMALL_SWORDS, SHIELDS; } + CWeaponSkillHits = { 2, 20, 20; } + PanicLevel = 50; + AutomaticallySeen = true; + ClothColor = rgb16(88, 50, 30); + HairColor = rgb16(100, 100, 100); + DeathMessage = "@Dd dies yelling \"FREEDOM!\""; + HostileReplies == "\"Get lost!\""; + FriendlyReplies = + { + 4, + "\"Hullo there friend!\""; + "@Dd salutes you solemnly \"Solidarity Brother!\""; + "@Dd grasps your shoulder \"Have you seen Molly? Is he well?\""; + "@Dd chortles \"You know you're on the steppe when your dog runs away and you can still see him running for at least three days.\""; + } + } + + Config BAND_LEADER; + { + AttributeBonus = 10; + Helmet = SILVER helmet; + BodyArmor = NYMPH_HAIR bodyarmor(PLATE_MAIL) { Enchantment = 2; } + RightWielded = SILVER meleeweapon(SPEAR) { SecondaryMaterial = OAK_WOOD; Enchantment = 2; } + Belt = NYMPH_HAIR belt { Enchantment = 2; } + RightBoot = HARDENED_LEATHER boot; + RightGauntlet = HARDENED_LEATHER gauntlet; + Cloak = FABRIC cloak { Enchantment = 8; } + Adjective = "roving"; + PostFix = "band-leader"; + KnownCWeaponSkills = { 2, POLE_ARMS, SHIELDS; } + CWeaponSkillHits = { 2, 40, 40; } + PanicLevel = 20; + AutomaticallySeen = true; + ClothColor = rgb16(70, 88, 42); + HairColor = rgb16(220, 220, 220); + DeathMessage = "@Dd dies yelling \"FREEDOM FOR TWERAIF!\""; + HostileReplies == "\"Piss off!\""; + FriendlyReplies = + { + 4, + "\"Hullo there traveller. We're UTFA.\""; + "@Dd steps forward \"I am the leader of our roving band of Forest Men (UTFA Soldiery).\""; + "@Dd embraces you \"Have you come to redeem us?\""; + "@Dd explains gravely \"Deep inside the forest is a prison where our kindred are being held. Visit Regii and the officials in the underground and help us free them.\""; + } + } +} + +kabouter +{ + DefaultArmStrength = 8; + DefaultLegStrength = 8; + DefaultDexterity = 12; + DefaultAgility = 16; + DefaultEndurance = 14; + DefaultPerception = 20; + DefaultIntelligence = 10; + DefaultWisdom = 20; + DefaultCharisma = 40; + DefaultMana = 0; + SkinColor = rgb16(206, 140, 96); + EyeColor = rgb16(0, 123, 223); + HairColor = rgb16(180, 180, 180); + ClothColor = rgb16(140, 0, 0); + CapColor = rgb16(160, 0, 0); + TorsoSpecialColor = rgb16(255, 236, 0); + LegMainColor = rgb16(140, 0, 0); + BootColor = rgb16(64, 0, 0); + HeadBitmapPos = 96, 704; + TorsoBitmapPos = 32, 704; + ArmBitmapPos = 64, 704; + LegBitmapPos = 0, 704; + TotalVolume = 20000; + TotalSize = 90; + NameSingular = "kabouter"; + HostileReplies == "@Dd grimaces furiously."; + FriendlyReplies == "@Dd smiles cheerfully."; + CanBeGenerated = true; + Sex = MALE; + RightWielded = SILVER BIRCH_WOOD meleeweapon(SICKLE); + KnownCWeaponSkills == SMALL_SWORDS; + CWeaponSkillHits == 30; + RightSWeaponSkillHits = 20; + PanicLevel = 50; + FleshMaterial = KABOUTER_FLESH; + DeathMessage = "@Dd dies with a yelp."; + AttachedGod = ATAVUS; + WieldedPosition = 2, 1; + Inventory = { 1, wand(WAND_OF_SLOW);} + FireResistance = 10; + ElectricityResistance = 10; + EnergyResistance = 10; + UndeadVersions = false; + RightBoot = BLACK_LEATHER boot { Enchantment = 1; } + Helmet = BLACK_LEATHER belt { Enchantment = 1; } + ClassStates = GAS_IMMUNITY|INFRA_VISION; +} + +regii +{ + DefaultArmStrength = 20; + DefaultLegStrength = 25; + DefaultDexterity = 15; + DefaultAgility = 20; + DefaultEndurance = 15; + DefaultPerception = 24; + DefaultIntelligence = 35; + DefaultWisdom = 10; + DefaultCharisma = 25; + DefaultMana = 10; + TotalVolume = 160000; + TotalSize = 160; + NameSingular = "UTFA resistance leader"; + Cloak = NYMPH_HAIR cloak { Enchantment = 1; } + BodyArmor = IRON bodyarmor(CHAIN_MAIL) { Enchantment = 1; } + Belt = BLACK_LEATHER belt(BELT_OF_CARRYING) { Enchantment = 2; } + RightWielded = STEEL meleeweapon(HALBERD) { Enchantment = 3; } + LeftRing = ring(RING_OF_INFRA_VISION); + RightGauntlet = NYMPH_HAIR gauntlet { Enchantment = 1; } + RightBoot = HARDENED_LEATHER boot(BOOT_OF_KICKING) { Enchantment = 1; } + KnownCWeaponSkills = { 2, POLE_ARMS, KICK; } + CWeaponSkillHits = { 2, 500, 500; } + RightSWeaponSkillHits = 500; + LeftSWeaponSkillHits = 500; + PanicLevel = 10; + TorsoBitmapPos = 48, 80; + HeadBitmapPos = 96, 224; + ArmBitmapPos = 64, 0; + LegBitmapPos = 0, 64; + ClothColor = rgb16(50, 50, 50); + HairColor = rgb16(244, 84, 4); + UsesLongArticle = true; + Inventory = { 6, stone, stone, stone, stone, stone, holybook(MELLIS); } + CanRead = true; + HostileReplies == "\"Bugger off!\""; + IsUnique = true; + IsNameable = false; + CanBeCloned = false; + DefaultName = "Regii"; + AttackStyle = USE_ARMS|USE_LEGS; + CriticalModifier = 4; + TamingDifficulty = NO_TAMING; + AttachedGod = MELLIS; + CanBeConfused = false; + IsPolymorphable = false; + FriendlyReplies = + { + 1, + "\"How goes your preparation for the mission brother?\""; + } + AutomaticallySeen = true; + ScienceTalkPossibility = 0; + UndeadVersions = false; +} + +UTFAOfficial +{ + DefaultArmStrength = 12; + DefaultLegStrength = 18; + DefaultDexterity = 14; + DefaultAgility = 14; + DefaultEndurance = 12; + DefaultPerception = 24; + DefaultIntelligence = 20; + DefaultWisdom = 10; + DefaultCharisma = 12; + DefaultMana = 10; + TotalVolume = 160000; + TotalSize = 160; + NameSingular = "UTFA (Official)"; + Cloak = LEATHER cloak { Enchantment = 1; } + BodyArmor = HARDENED_LEATHER bodyarmor(PLATE_MAIL) { Enchantment = 2; } + Belt = BLACK_LEATHER belt; + RightWielded = IRON meleeweapon(WAR_HAMMER) { Enchantment = 2; } + RightGauntlet = LEATHER gauntlet { Enchantment = 1; } + RightBoot = HARDENED_LEATHER boot; + KnownCWeaponSkills = { 2, BLUNT_WEAPONS, KICK; } + CWeaponSkillHits = { 2, 500, 200; } + RightSWeaponSkillHits = 500; + LeftSWeaponSkillHits = 500; + PanicLevel = 10; + TorsoBitmapPos = 48, 48; + HeadBitmapPos = 96, 160; + ArmBitmapPos = 64, 16; + LegBitmapPos = 0, 64; + ClothColor = rgb16(100, 80, 54); + /*HairColor = rgb16(244, 84, 4);*/ + UsesLongArticle = false; + Inventory = { 6, stone, stone, stone, stone, stone, holybook(MELLIS); } + CanRead = true; + HostileReplies == "\"Naff off!\""; + IsUnique = false; + IsNameable = false; + CanBeCloned = false; + /*DefaultName = "";*/ /*Meriwether, Paul, Tiffany, Randolph, Junket*/ + AttackStyle = USE_ARMS|USE_LEGS; + CriticalModifier = 4; + TamingDifficulty = NO_TAMING; + AttachedGod = SILVA; + CanBeConfused = false; + IsPolymorphable = false; + FriendlyReplies == "\"Welcome brother! And solidarity to you!\""; + AutomaticallySeen = true; + ScienceTalkPossibility = 0; + UndeadVersions = false; + CanBeGenerated = false; +} diff --git a/Script/char_14.dat b/Script/char_14.dat index f80136d..6b1d2b3 100644 --- a/Script/char_14.dat +++ b/Script/char_14.dat @@ -44,3 +44,320 @@ mangogrower ScienceTalkWisdomRequirement = 10; IsMasochist = true; } + +firefox +{ + DefaultArmStrength = 8; + DefaultAgility = 20; + DefaultEndurance = 8; + DefaultPerception = 20; + DefaultIntelligence = 6; + DefaultWisdom = 5; + DefaultCharisma = 12; + DefaultMana = 0; + TotalVolume = 25000; + TorsoBitmapPos = 256, 96; + HostileReplies == "@Dd yaps in fury."; + FriendlyReplies == "@Dd yaps gleefully."; + TotalSize = 80; + SkinColor = rgb16(180, 100, 40); + TorsoMainColor = rgb16(239, 239, 220); /* the tail */ + Adjective = "fire"; + NameSingular = "fox"; + NamePlural = "foxes"; + Alias == "foxy"; + BaseBiteStrength = 425; + CanBeGenerated = true; + CWeaponSkillHits == 100; + ClassStates = INFRA_VISION; + FleshMaterial = FOX_FLESH; + AttachedGod = SILVA; + DeathMessage = "@Dd is killed."; + BaseEmitation = rgb24(150, 120, 90); + Frequency = 500; +} + +thunderbird +{ + DefaultArmStrength = 2; + DefaultAgility = 40; + DefaultEndurance = 8; + DefaultPerception = 20; + DefaultIntelligence = 6; + DefaultWisdom = 5; + DefaultCharisma = 6; + DefaultMana = 0; + StandVerb = "flying"; + CanOpen = false; + TotalVolume = 500; + TorsoBitmapPos = 560, 0; + HostileReplies == "@Dd peeps thunderously."; + FriendlyReplies == "@Dd chirps happily."; + TotalSize = 20; + SkinColor = rgb16(142, 100, 50); + TorsoMainColor = rgb16(220, 180, 0); + Adjective = "thunder"; + NameSingular = "bird"; + AttackStyle = USE_HEAD; + BaseBiteStrength = 400; + CanBeGenerated = true; + KnownCWeaponSkills == BITE; + CWeaponSkillHits == 50; + PanicLevel = 75; + FleshMaterial = THUNDER_BIRD_FLESH; + AttachedGod = SILVA; + BiteCapturesBodyPart = false; + MoveType = FLY; + BaseEmitation = rgb24(130, 130, 130); + DangerModifier = 500; + Frequency = 500; + HPRequirementForGeneration = 70; + DayRequirementForGeneration = 3; +} + +anvitas +{ + DefaultArmStrength = 70; + DefaultAgility = 50; + DefaultEndurance = 30; + DefaultPerception = 33; + DefaultIntelligence = 8; + DefaultWisdom = 7; + DefaultCharisma = 16; + DefaultMana = 0; + TorsoBitmapPos = 192, 96; + HostileReplies == "@Dd roars terribly."; + FriendlyReplies == "@Dd roars cheerfully."; + SkinColor = rgb16(140, 90, 100); + TorsoSpecialColor = rgb16(165, 4, 61); + NameSingular = "hedgehog"; + Adjective = "gigantic mutant"; + AttackStyle = USE_HEAD; + BaseUnarmedStrength = 1000; + BaseBiteStrength = 500; + KnownCWeaponSkills == BITE; + CWeaponSkillHits == 250; + FleshMaterial = MUTANT_HEDGEHOG_FLESH; + AttachedGod = SCABIES; + TotalSize = 300; + MoveType = WALK; + DestroysWalls = true; + DefaultName = "Anvitas"; + Alias == "Anvitas"; + TotalVolume = 600000; + IsUnique = true; + CanApply = true; + IsPolymorphable = false; + CanBeCloned = false; + BloodMaterial = GLOWING_BLOOD; +} + +genefourxvesana +{ + DefaultArmStrength = 32; + DefaultAgility = 16; + DefaultEndurance = 20; + DefaultPerception = 32; + DefaultIntelligence = 24; + DefaultWisdom = 16; + DefaultCharisma = 3; + DefaultMana = 0; + TotalVolume = 60000; + TorsoBitmapPos = 128, 64; + TotalSize = 350; + Adjective = "grandmother carnivorous"; + NameSingular = "mutant plant"; + DefaultName = "genefourx vesana"; + AttackStyle = USE_HEAD; + BaseBiteStrength = 1600; + SkinColor = rgb16(111, 64, 37); + TorsoMainColor = rgb16(0, 160, 0); /* the leaves */ + TorsoSpecialColor = rgb16(220, 0, 0); + KnownCWeaponSkills == BITE; + CWeaponSkillHits == 100; + PanicLevel = 0; + TamingDifficulty = NO_TAMING; + IsNameable = false; + IsUnique = true; + DeathMessage = "@Dd is brutally destroyed."; + BaseEmitation = rgb24(140, 100, 100); + FleshMaterial = MUTANT_PLANT_FIBER; + AttachedGod = SCABIES; + IsPlant = true; + CanOpen = false; + HostileReplies == "@Dd produces a gutteral roaring noise."; + FriendlyReplies == "@Dd produces a gutteral purring noise."; + ClassStates = INFRA_VISION; + HasALeg = false; + SpillsBlood = false; + Sweats = false; + StandVerb = "rooted"; + IsRooted = true; + AllowUnconsciousness = false; + Sex = FEMALE; +} + +haastseagle +{ + DefaultArmStrength = 60; + DefaultAgility = 30; + DefaultEndurance = 25; + DefaultPerception = 30; + DefaultIntelligence = 10; + DefaultWisdom = 7; + DefaultCharisma = 5; + DefaultMana = 0; + TorsoBitmapPos = 128, 128; + HostileReplies == "@Dd cries bloodcurdlingly."; + FriendlyReplies == "@Dd cries cheerfully."; + SkinColor = rgb16(128, 102, 70); + TorsoMainColor = rgb16(255, 255, 0); + TorsoSpecialColor = rgb16(148, 148, 120); + NameSingular = "haast's eagle"; + Adjective = "enormous"; + UsesLongAdjectiveArticle = true; + AttackStyle = USE_HEAD; + BaseBiteStrength = 800; + KnownCWeaponSkills == BITE; + CWeaponSkillHits == 200; + FleshMaterial = EAGLE_FLESH; + AttachedGod = SILVA; + TotalSize = 200; + MoveType = FLY; + TotalVolume = 24000; + IsPolymorphable = false; + CanBeCloned = false; + StandVerb = "flying"; + CanOpen = false; + CanBeGenerated = true; + /*ClassStates = INFRA_VISION;*/ + BiteCapturesBodyPart = true; + MoveType = FLY; + IsCatacombCreature = false; +} + +bluedragon +{ + DefaultArmStrength = 30; + DefaultAgility = 40; + DefaultEndurance = 50; + DefaultPerception = 42; + DefaultIntelligence = 30; + DefaultWisdom = 30; + DefaultCharisma = 20; + DefaultMana = 0; + TotalVolume = 50000; + TorsoBitmapPos = 354, 0; + HostileReplies == "@Dd glares at you."; + FriendlyReplies == "@Dd happily wiggles its tail."; + TotalSize = 40; + SkinColor = rgb16(0, 20, 180); + EyeColor = rgb16(255, 255, 255); + NameSingular = "blue dragon"; + AttackStyle = USE_HEAD; + BaseBiteStrength = 600; + CanBeGenerated = true; + KnownCWeaponSkills == BITE; + CWeaponSkillHits == 250; + FleshMaterial = JACKAL_FLESH; + Frequency = 1000; + CanRead = true; + ElectricityResistance = 100; +} + +reddragon +{ + DefaultArmStrength = 30; + DefaultAgility = 40; + DefaultEndurance = 50; + DefaultPerception = 42; + DefaultIntelligence = 30; + DefaultWisdom = 30; + DefaultCharisma = 20; + DefaultMana = 0; + TotalVolume = 50000; + TorsoBitmapPos = 354, 0; + HostileReplies == "@Dd glares at you."; + FriendlyReplies == "@Dd happily wiggles its tail."; + TotalSize = 40; + SkinColor = rgb16(180, 20, 0); + EyeColor = rgb16(255, 255, 255); + NameSingular = "red dragon"; + AttackStyle = USE_HEAD; + BaseBiteStrength = 600; + CanBeGenerated = true; + KnownCWeaponSkills == BITE; + CWeaponSkillHits == 250; + FleshMaterial = JACKAL_FLESH; + Frequency = 1000; + CanRead = true; + FireResistance = 100; +} + +fruitbat +{ + DefaultArmStrength = 2; + DefaultAgility = 40; + DefaultEndurance = 8; + DefaultPerception = 24; + DefaultIntelligence = 7; + DefaultWisdom = 5; + DefaultCharisma = 10; + DefaultMana = 0; + StandVerb = "flying"; + CanOpen = false; + TotalVolume = 1000; + TorsoBitmapPos = 464, 16; + HostileReplies == "@Dd squeaks rapaciously."; + FriendlyReplies == "@Dd squeaks happily."; + TotalSize = 20; + SkinColor = rgb16(190, 130, 64); + TorsoMainColor = rgb16(180, 180, 180); + NameSingular = "fruit bat"; + AttackStyle = USE_HEAD; + BaseBiteStrength = 100; + CanBeGenerated = true; + KnownCWeaponSkills == BITE; + CWeaponSkillHits == 20; + PanicLevel = 75; + FleshMaterial = BAT_FLESH; + AttachedGod = CLEPTIA; + ClassStates = INFRA_VISION; /* So that invisible player doesn't screw the AI */ + BiteCapturesBodyPart = false; + MoveType = FLY; +} + +okapi +{ + DefaultArmStrength = 25; + DefaultAgility = 15; + DefaultEndurance = 20; + DefaultPerception = 18; + DefaultIntelligence = 5; + DefaultWisdom = 8; + DefaultCharisma = 10; + DefaultMana = 0; + TotalVolume = 40000; + TorsoBitmapPos = 304, 112; + HostileReplies == "@Dd whinneys vengefully."; + FriendlyReplies == "@Dd whinneys cheerfully."; + TotalSize = 150; + SkinColor = rgb16(108, 30, 18); + TorsoMainColor = rgb16(238, 234, 210); + TorsoSpecialColor = rgb16(108, 30, 18); + NameSingular = "okapi"; + NamePlural = "okapies"; + AttackStyle = USE_HEAD; + BaseBiteStrength = 180; + CanBeGenerated = true; + KnownCWeaponSkills == BITE; + CWeaponSkillHits == 20; + FleshMaterial = OKAPI_FLESH; + DeathMessage = "@Dd whinneys one last time and dies."; + AttachedGod = SCABIES; + AutomaticallySeen = true; + IsSadist = true; + IsMasochist = true; + CanZap = true; + UsesLongArticle = true; +} diff --git a/Script/define.dat b/Script/define.dat index ce670e4..f4effde 100644 --- a/Script/define.dat +++ b/Script/define.dat @@ -864,6 +864,12 @@ #enum { + ROVER = 1, + BAND_LEADER, +}; + + +#enum { FIELD_MOUSE = 1, LABORATORY_MOUSE, }; @@ -873,6 +879,10 @@ #define STARVED_OX 1 +#define FLOATIE 1 + +#define SONIC 1 + /* Least significant bit defines sex */ #enum { @@ -1025,7 +1035,6 @@ UNDER_WATER_TUNNEL, MONDEDR, MUNTUO, - // undone DRAGON_TOWER, DARK_FOREST, XINROCH_TOMB, diff --git a/Script/dungeon.dat b/Script/dungeon.dat index 19dad64..8706417 100644 --- a/Script/dungeon.dat +++ b/Script/dungeon.dat @@ -21,7 +21,7 @@ /* Team and dungeon data for the game */ -Dungeons = 6; +Dungeons = 9; Teams = 17; /* @@ -140,3 +140,6 @@ Include "dungeons/UT.dat"; Include "dungeons/GC.dat"; Include "dungeons/mondedr.dat"; Include "dungeons/muntuo.dat"; +Include "dungeons/xinrochtomb.dat"; +Include "dungeons/dragontower.dat"; +Include "dungeons/darkforest.dat"; diff --git a/Script/dungeons/darkforest.dat b/Script/dungeons/darkforest.dat new file mode 100644 index 0000000..18770de --- /dev/null +++ b/Script/dungeons/darkforest.dat @@ -0,0 +1,2141 @@ +Dungeon DARK_FOREST; +{ + Levels = 11; + Description = "deep forest"; + ShortDescription = "DF"; + + LevelDefault + { + FillSquare = solidterrain(DARK_GRASS_TERRAIN), 0; + Size = 60, 60; + Rooms = 5; + Items = 0; /* this must be zero for these levels */ + GenerateMonsters = true; + IsOnGround = true; + TeamDefault = MONSTER_TEAM; + LOSModifier = 64; + IgnoreDefaultSpecialSquares = false; + DifficultyBase = 30; + DifficultyDelta = 5; + MonsterAmountBase = 6; + MonsterAmountDelta = 3; + MonsterGenerationIntervalBase = 200; + MonsterGenerationIntervalDelta = -20; + CanGenerateBone = true; + ItemMinPriceBase = 10; + ItemMinPriceDelta = 5; + EnchantmentMinusChanceBase = -5; + EnchantmentMinusChanceDelta = 0; + EnchantmentPlusChanceBase = 6; + EnchantmentPlusChanceDelta = 2; + BackGroundType = GREEN_FRACTAL; + AutoReveal = false; + IsCatacomb = false; + + RoomDefault + { + Pos = 2:XSize-5,2:YSize-5; + Size = 4:7,4:7; + AltarPossible = false; + WallSquare = solidterrain(GRASS_TERRAIN), LIME_STONE wall(BRICK_OLD); + FloorSquare = FIR_WOOD solidterrain(PARQUET), 0; + DoorSquare = solidterrain(GRASS_TERRAIN), FIR_WOOD door; + GenerateDoor = true; + DivineMaster = 0; + GenerateTunnel = false; + GenerateLanterns = false; + Type = ROOM_NORMAL; + GenerateFountains = false; + AllowLockedDoors = true; + AllowBoobyTrappedDoors = true; + Shape = RECTANGLE; + IsInside = true; + GenerateWindows = false; + UseFillSquareWalls = false; + Flags = 0; + GenerateWards = false; + } + } + + Level 0; + { + Size = 50, 50; + LevelMessage = "You step inside the deep forest"; + Rooms = 2; + Items = 1:5; + + RoomDefault + { + AllowLockedDoors = false; + } + + Room + { + Pos = 10,10; + Size = 6,4; + AllowLockedDoors = false; + AllowBoobyTrappedDoors = false; + WallSquare = solidterrain(GROUND), BASALT earth; + FloorSquare = solidterrain(GROUND), 0; + GenerateDoor = false; + + OTerrainMap + { + Pos = 0,0; + Size = 6,4; + Types + { + # = 0; + $ = GRANITE wall(BRICK_OLD); + d = FIR_WOOD door; + % = BASALT earth; + } + } + { + %%%%%% + %....% + %..$.% + %$$$d$ + } + + Square, Pos 2,2; + { + OTerrain = stairs(STAIRS_DOWN) { AttachedArea = 1; } + EntryIndex = STAIRS_DOWN; + } + } + + Room + { + Pos = 25:XSize-10,25:YSize-10; + Size = 5,5; + WallSquare = solidterrain(GRASS_TERRAIN), GRANITE wall(BRICK_OLD); + GenerateWindows = false; + AllowLockedDoors = false; + GenerateDoor = false; + GenerateLanterns = true; + + OTerrainMap + { + Pos = 0,0; + Size = 5,5; + Types + { + # = 0; + $ = GRANITE wall(BRICK_OLD); + d = FIR_WOOD door; + } + } + { + $$$$$ + $...$ + $...$ + $...$ + $$d$$ + } + + CharacterMap + { + Pos = 1,1; + Size = 3,3; + Types + { + _ = 0; + # = 0; + b = fruitbat; + + } + } + { + ..b + b.. + .b. + } + + GTerrainMap + { + Pos = 1,1; + Size = 3,3; + Types + { + # = FIR_WOOD solidterrain(PARQUET); + } + } + { + ### + ### + ### + } + + ItemMap + { + Pos = 1,1; + Size = 3,3; + Types + { + C == OAK_WOOD itemcontainer(LARGE_CHEST) { ItemsInside = { 3, Random { MaxPrice = 150; Category = WEAPON|SHIELD; ConfigFlags = NO_BROKEN; Times = 3;}, Random { MaxPrice = 150; Category = HELMET|BELT; ConfigFlags = NO_BROKEN; Enchantment = 1; Times = 3;}, Random { MaxPrice = 63; Category = CLOAK|BODY_ARMOR; ConfigFlags = NO_BROKEN; Times = 2;} } } + } + } + { + .C. + ... + ... + } + } + + Square, Pos 13, 14; + { + OTerrain = sign { Text = "UTFA Headquarters"; } + } + + Square, Random NOT_IN_ROOM|HAS_NO_OTERRAIN; + { + OTerrain = decoration(FIR); + Times = 300; + } + Square, Random NOT_IN_ROOM|HAS_NO_OTERRAIN; + { + OTerrain = decoration(PINE); + Times = 60; + } + Square, Random NOT_IN_ROOM|HAS_NO_OTERRAIN; + { + OTerrain = decoration(BIRCH); + Times = 30; + } + Square, Random NOT_IN_ROOM|HAS_NO_OTERRAIN; + { + OTerrain = decoration(OAK); + Times = 10; + } + + Square, Pos 45,5; + { + OTerrain = stairs(WAYPOINT_DEEPER) { AttachedArea = 2; AttachedEntry = WAYPOINT_SHALLOWER; } + EntryIndex = WAYPOINT_DEEPER; /*EntryIndex = STAIRS_DOWN + 1;*/ + } + + Square, Pos 12, 45; + { + Character = forestman(ROVER) { Team = FORESTMAN_TEAM; } + } + + Square, Pos 12, 43; + { + Character = forestman(ROVER) { Team = FORESTMAN_TEAM; } + } + Square, Pos 10, 43; + { + Character = forestman(ROVER) { Team = FORESTMAN_TEAM; } + } + Square, Pos 10, 45; + { + Character = forestman(ROVER) { Team = FORESTMAN_TEAM; } + } + Square, Pos 11, 44; + { + Character = forestman(BAND_LEADER) { Team = FORESTMAN_TEAM; Flags = IS_LEADER; } + } + + Square, Pos 0, 45; + { + EntryIndex = STAIRS_UP; + } + + Square, Pos 5, 45; + { + OTerrain = sign { Text = "The Deep Forest"; } + } + Square, Pos 6, 45; + { + Items == lantern; + } + + Square, Pos 32, 45; + { + Character = kobold; + } + + Square, Pos 32, 43; + { + Character = kobold; + } + Square, Pos 30, 43; + { + Character = kobold; + } + Square, Pos 30, 45; + { + Character = kobold(CHIEFTAIN); + } + Square, Pos 31, 44; + { + Character = kobold(LORD) { Flags = IS_LEADER; } + } + } + + Level 1;/* underground store */ + { + FillSquare = solidterrain(GROUND), BASALT earth; + TunnelSquare = solidterrain(GROUND), 0; + LevelMessage = "It is very dark in this underground store"; + /*Description = "Underground Store";*/ + ShortDescription = "DF Store"; + Size = 44, 38; + Rooms = 2; + IsOnGround = false; + LOSModifier = 16; + BackGroundType = GRAY_FRACTAL; + CanGenerateBone = false; + GenerateMonsters = false; + + RoomDefault + { + /*Pos = 2:XSize-5,2:YSize-5; + Size = 4:6,4:6;*/ + WallSquare = solidterrain(GROUND), GRANITE wall(BRICK_OLD); + FloorSquare = FIR_WOOD solidterrain(PARQUET), 0; + DoorSquare = FIR_WOOD solidterrain(GROUND), FIR_WOOD door; + GenerateTunnel = true; + GenerateWards = false; + } + + Room + { + Pos = 2:XSize-10,2:YSize-8; + Size = 8,5; + AllowLockedDoors = false; + AllowBoobyTrappedDoors = false; + GenerateTunnel = true; + + OTerrainMap + { + Pos = 0,0; + Size = 8,5; + Types + { + # = 0; + $ = GRANITE wall(BRICK_OLD); + d = FIR_WOOD door; + } + } + { + $$$$$$$$ + $......$ + $......$ + $......$ + $$$$$$$$ + } + + Square, Random IN_ROOM|HAS_NO_OTERRAIN; + { + OTerrain = stairs(STAIRS_UP) { AttachedArea = 0; } + EntryIndex = STAIRS_UP; + } + + Square, Random; + { + Items == brokenbottle; + Times = 3; + } + + } + + Room + { + Pos = 2:XSize-12,2:YSize-14; + Size = 11,13; + GenerateDoor = true; + GenerateTunnel = true; + Flags = NO_MONSTER_GENERATION; + + OTerrainMap + { + Pos = 0,0; + Size = 11,13; + Types + { + # = 0; + $ = GRANITE wall(BRICK_OLD); + d = FIR_WOOD door; + = = olterraincontainer(BOOK_CASE) { ItemsInside = { 3, Random { MaxPrice = 500; Category = SCROLL; }, Random { MaxPrice = 500; Category = BOOK; }, scrollofdetectmaterial; } } + } + } + { + ........... + ........... + ..$$$$$$$.. + ..=.....$.. + ..$.....$.. + ..$.....$.. + ..$.....$.. + ..$.....$.. + ..$.....$.. + ..$.....$.. + ..$$$$$$$.. + ........... + ........... + } + + CharacterMap + { + Pos = 3,3; + Size = 5,7; + Types + { + _ = 0; + # = 0; + R = regii { Team = FORESTMAN_TEAM; } + O = UTFAOfficial { Team = FORESTMAN_TEAM; } + } + } + { + ..... + O.... + ...O. + .O... + ....O + O.... + ..R.. + } + + Square, Random; + { + Items == can { SecondaryMaterial = BANANA_FLESH; } + Times = 2; + } + } + } + + RandomLevel 2:3; + { + /*Room Dolphin Pond*/ + Room + { + Pos = 20:XSize-30,20:YSize-30; + Size = 7,7; + GenerateLanterns = false; + GenerateWindows = false; + AllowLockedDoors = false; + AllowBoobyTrappedDoors = false; + GenerateFountains = false; + AltarPossible = false; + GenerateDoor = false; + GenerateLanterns = false; + GenerateWards = false; + WallSquare = solidterrain(DARK_GRASS_TERRAIN), 0; + FloorSquare = solidterrain(DARK_GRASS_TERRAIN), 0; + + OTerrainMap + { + Pos = 0,0; + Size = 7,7; + Types + { + $ = GRANITE wall(BRICK_OLD); + } + } + { + ....... + ....... + ....... + ....... + ....... + ....... + ....... + } + + GTerrainMap + { + Pos = 0,0; + Size = 7,7; + Types + { + # = WATER liquidterrain(POOL); + B = FIR_WOOD solidterrain(PARQUET); + } + } + { + #####.. + ######. + ####### + ####### + ####### + .###### + ..##### + } + CharacterMap + { + Pos = 0,0; + Size = 7,7; + Types + { + d = dolphin; + } + } + { + ....... + ....... + ..d.... + ....... + ....... + ....... + ....... + } + } + + Square, Random NOT_IN_ROOM; + { + Character = haastseagle; + Times = 1; + } + } + + RandomLevel 2:3; + { + /*Dwarven minefield A*/ + Room + { + Pos = 2:XSize-8,2:YSize-8; + Size = 6:10, 5:8; + AllowLockedDoors = false; + AllowBoobyTrappedDoors = false; + Shape = ROUND_CORNERS; + GenerateDoor = false; + GenerateLanterns = false; + AltarPossible = false; + GenerateWards = false; + IsInside = false; + Flags = NO_MONSTER_GENERATION; + UseFillSquareWalls = true; + GenerateWards = false; + WallSquare = solidterrain(DARK_GRASS_TERRAIN), 0; + FloorSquare = solidterrain(DARK_GRASS_TERRAIN), 0; + DoorSquare = solidterrain(DARK_GRASS_TERRAIN), 0; + + Square, Random; + { + OTerrain = STEEL sign { Text = "Dwarven mine field 214"; } + } + + Square, Random; + { + Items == Random { MinPrice = 100; Chance = 50; } + Times = 8; + } + + Square, Random; + { + Items == Random { MinPrice = 500; Chance = 50; } + Times = 2; + } + + Square, Random; + { + Items == mine { Team = MONSTER_TEAM; IsActive = true; Chance = 25; } + Times = 18; + } + + Square, Random; + { + Items == mine(BIG_MINE) { Team = MONSTER_TEAM; IsActive = true; Chance = 25; } + Times = 6; + } + } + } + + RandomLevel 3:4; + { + /*Dwarven minefield B*/ + Room + { + Pos = 2:XSize-10,2:YSize-10; + Size = 5:8, 8:10; + AllowLockedDoors = false; + AllowBoobyTrappedDoors = false; + Shape = ROUND_CORNERS; + WallSquare = solidterrain(DARK_GRASS_TERRAIN), 0; + FloorSquare = solidterrain(DARK_GRASS_TERRAIN), 0; + DoorSquare = solidterrain(DARK_GRASS_TERRAIN), 0; + GenerateDoor = false; + GenerateLanterns = false; + AltarPossible = false; + GenerateWards = false; + IsInside = false; + Flags = NO_MONSTER_GENERATION; + UseFillSquareWalls = true; + GenerateWards = false; + + Square, Random; + { + OTerrain = STEEL sign { Text = "Dwarven mine field 625"; } + } + + Square, Random; + { + Items == Random { MinPrice = 200; Chance = 50; } + Times = 12; + } + + Square, Random; + { + Items == Random { MinPrice = 500; Chance = 50; } + Times = 2; + } + + Square, Random; + { + Items == mine { Team = MONSTER_TEAM; IsActive = true; Chance = 25; } + Times = 18; + } + + Square, Random; + { + Items == mine(BIG_MINE) { Team = MONSTER_TEAM; IsActive = true; Chance = 25; } + Times = 6; + } + } + } + + RandomLevel 3:4; + { + /*Room Rock cave with cave bears*/ + + Room /* mountain */ + { + Pos = 2:XSize-10,2:YSize-10; + Size = 8, 8; + AllowLockedDoors = false; + AllowBoobyTrappedDoors = false; + GenerateFountains = false; + Shape = ROUND_CORNERS; + GenerateDoor = false; + GenerateLanterns = false; + AltarPossible = false; + GenerateWards = false; + UseFillSquareWalls = true; + FloorSquare = solidterrain(DARK_GRASS_TERRAIN), 0; + DoorSquare = solidterrain(DARK_GRASS_TERRAIN), 0; + + OTerrainMap + { + Pos = 0,0; + Size = 8,8; + Types + { + % = LIME_STONE earth; + d = GRANITE door; + } + } + { + .%%%%%%. + %%..%.%% + %...d..% + %..%%..% + %%%%..%% + .%%...%. + ..%..%%. + ..%..%.. + } + + CharacterMap + { + Pos = 0,0; + Size = 8,8; + + Types + { + c = bear(CAVE_BEAR); + } + } + { + ........ + ........ + ..c..... + .c...... + ........ + ........ + ........ + ........ + } + } + } + + RandomLevel 4:5; + { + Square, Random NOT_IN_ROOM; + { + Character = necromancer(APPRENTICE); + Times = 1; + } + } + + /*level 2 = chaotic shrine*/ + /*level 3 = guaranteed benign Uldra*/ + /*level 4 = shop (wherever this is, you can't generate bones)*/ + /*level 5 = Rock formation and Lawful shrine*/ + /*level 6 = catacomb with mutant bunny room and guaranteed vampire*/ + /*level 7 = Morbe's abode*/ + /*level 8 = Bridge level*/ + /*level 9 = Underground Passage*/ + /*level 10 = Prison Level*/ + + Level 2; + { + LevelMessage = "You step further inside the deep forest"; + LOSModifier = 48; + + RoomDefault + { + GenerateWards = false; + AllowLockedDoors = false; + AllowBoobyTrappedDoors = false; + } + + Room + { + Pos = 5:15,5:15; + Size = 1, 1; + GenerateDoor = false; + GenerateLanterns = false; + AltarPossible = false; + GenerateFountains = false; + AllowLockedDoors = false; + AllowBoobyTrappedDoors = false; + Shape = RECTANGLE; + WallSquare = solidterrain(DARK_GRASS_TERRAIN), 0; + FloorSquare = solidterrain(DARK_GRASS_TERRAIN), 0; + DoorSquare = solidterrain(DARK_GRASS_TERRAIN), 0; + IsInside = false; + Flags = NO_MONSTER_GENERATION; + UseFillSquareWalls = true; + GenerateWards = false; + + Square, Pos 0, 0; + { + OTerrain = stairs(WAYPOINT_SHALLOWER) { AttachedArea = 0; AttachedEntry = WAYPOINT_DEEPER; } /*STAIRS_DOWN + 1;*/ + EntryIndex = WAYPOINT_SHALLOWER; /*EntryIndex = STAIRS_UP;*/ + } + } + + Room + { + Pos = XSize-15:XSize-5,XSize-15:XSize-5; + Size = 1, 1; + GenerateDoor = false; + GenerateLanterns = false; + AltarPossible = false; + GenerateFountains = false; + AllowLockedDoors = false; + AllowBoobyTrappedDoors = false; + Shape = RECTANGLE; + WallSquare = solidterrain(DARK_GRASS_TERRAIN), 0; + FloorSquare = solidterrain(DARK_GRASS_TERRAIN), 0; + DoorSquare = solidterrain(DARK_GRASS_TERRAIN), 0; + IsInside = false; + Flags = NO_MONSTER_GENERATION; + UseFillSquareWalls = true; + GenerateWards = false; + + Square, Pos 0, 0; + { + OTerrain = stairs(WAYPOINT_DEEPER) { AttachedArea = 3; AttachedEntry = WAYPOINT_SHALLOWER; } + EntryIndex = WAYPOINT_DEEPER; + } + } + + /*holy shrine number 1*/ + Room + { + Pos = 2:XSize-8,2:YSize-9; + Size = 4:7, 4:7; + AllowLockedDoors = false; + AllowBoobyTrappedDoors = false; + Shape = ROUND_CORNERS; + WallSquare = solidterrain(DARK_GRASS_TERRAIN), 0; + FloorSquare = solidterrain(DARK_GRASS_TERRAIN), 0; + DoorSquare = solidterrain(DARK_GRASS_TERRAIN), 0; + GenerateDoor = false; + GenerateLanterns = false; + AltarPossible = false; + GenerateWards = true; + IsInside = false; + Flags = NO_MONSTER_GENERATION; + UseFillSquareWalls = true; + + Square, Random; + { + OTerrain = BASALT altar; + } + Square, Random; + { + Items == bone; + Times = 5; + } + Square, Random; + { + Items == skull; + Times = 2; + } + + Square, Random; + { + Items == Random { MinPrice = 20; Chance = 50; } + Times = 4; + } + + Square, Random; + { + Items == lantern; + Times = 2; + } + } + + Square, Random NOT_IN_ROOM|HAS_NO_OTERRAIN; + { + OTerrain = decoration(FIR); + Times = 600; + } + Square, Random NOT_IN_ROOM|HAS_NO_OTERRAIN; + { + OTerrain = decoration(PINE); + Times = 180; + } + Square, Random NOT_IN_ROOM|HAS_NO_OTERRAIN; + { + OTerrain = decoration(BIRCH); + Times = 90; + } + Square, Random NOT_IN_ROOM|HAS_NO_OTERRAIN; + { + OTerrain = decoration(OAK); + Times = 30; + } + + Square, Random NOT_IN_ROOM; + { + Character = kobold; + Times = 4:8; + } + Square, Random NOT_IN_ROOM; + { + Character = kobold(CHIEFTAIN); + Times = 1:2; + } + Square, Random NOT_IN_ROOM; + { + Items == TIN beartrap { Team = MONSTER_TEAM; IsActive = true; } + Times = 4:8; + } + Square, Random NOT_IN_ROOM; + { + Items == BRONZE beartrap { Team = MONSTER_TEAM; IsActive = true; } + Times = 2:4; + } + Square, Random NOT_IN_ROOM; + { + Items == METEORIC_STEEL beartrap { Team = MONSTER_TEAM; IsActive = true; } + Times = 0:2; + } + } + + Level 3; + { + LOSModifier = 32; + LevelMessage = "You step further inside the deep forest"; + + RoomDefault + { + GenerateWards = false; + } + + Room + { + Pos = 5:15,(YSize-15):(YSize-5); + Size = 1, 1; + GenerateDoor = false; + GenerateLanterns = false; + AltarPossible = false; + GenerateFountains = false; + AllowLockedDoors = false; + AllowBoobyTrappedDoors = false; + Shape = RECTANGLE; + WallSquare = solidterrain(DARK_GRASS_TERRAIN), 0; + FloorSquare = solidterrain(DARK_GRASS_TERRAIN), 0; + DoorSquare = solidterrain(DARK_GRASS_TERRAIN), 0; + IsInside = false; + Flags = NO_MONSTER_GENERATION; + UseFillSquareWalls = true; + GenerateWards = false; + + Square, Pos 0, 0; + { + OTerrain = stairs(WAYPOINT_SHALLOWER) { AttachedArea = 2; AttachedEntry = WAYPOINT_DEEPER; } + EntryIndex = WAYPOINT_SHALLOWER; + } + } + + Room + { + Pos = XSize-15:XSize-5,5:15; + Size = 1, 1; + GenerateDoor = false; + GenerateLanterns = false; + AltarPossible = false; + GenerateFountains = false; + AllowLockedDoors = false; + AllowBoobyTrappedDoors = false; + Shape = RECTANGLE; + WallSquare = solidterrain(DARK_GRASS_TERRAIN), 0; + FloorSquare = solidterrain(DARK_GRASS_TERRAIN), 0; + DoorSquare = solidterrain(DARK_GRASS_TERRAIN), 0; + IsInside = false; + Flags = NO_MONSTER_GENERATION; + UseFillSquareWalls = true; + GenerateWards = false; + + Square, Pos 0, 0; + { + OTerrain = stairs(WAYPOINT_DEEPER) { AttachedArea = 4; AttachedEntry = WAYPOINT_SHALLOWER; } + EntryIndex = WAYPOINT_DEEPER; + } + } + + Square, Random NOT_IN_ROOM|HAS_NO_OTERRAIN; + { + OTerrain = decoration(FIR); + Times = 600; + } + Square, Random NOT_IN_ROOM|HAS_NO_OTERRAIN; + { + OTerrain = decoration(PINE); + Times = 180; + } + Square, Random NOT_IN_ROOM|HAS_NO_OTERRAIN; + { + OTerrain = decoration(BIRCH); + Times = 190; + } + Square, Random NOT_IN_ROOM|HAS_NO_OTERRAIN; + { + OTerrain = decoration(OAK); + Times = 30; + } + + Square, Random; + { + Items == METEORIC_STEEL beartrap { Team = MONSTER_TEAM; IsActive = true; } + Times = 2:6; + } + + Square, Random NOT_IN_ROOM; + { + Character = bat; + Times = 4; + } + Square, Random NOT_IN_ROOM; + { + Character = magpie; + Times = 2; + } + Square, Random NOT_IN_ROOM; + { + Character = kobold; + Times = 4:8; + } + Square, Random NOT_IN_ROOM; + { + Character = kobold(CHIEFTAIN); + Times = 1:2; + } + Square, Random NOT_IN_ROOM; + { + Character = kobold(LORD); + Times = 1:2; + } + Square, Random NOT_IN_ROOM; + { + Character = hunter; + Times = 1; + } + Square, Random NOT_IN_ROOM; + { + Character = bear(BLACK_BEAR); + Times = 3:6; + } + } + + Level 4; + { + LevelMessage = "You step further inside the deep forest"; + LOSModifier = 32; + Size = 80, 40; + CanGenerateBone = false; + + RoomDefault + { + GenerateWards = false; + } + + Room + { + Pos = 1:7,5:YSize-5; + Size = 1, 1; + GenerateDoor = false; + GenerateLanterns = false; + AltarPossible = false; + GenerateFountains = false; + AllowLockedDoors = false; + AllowBoobyTrappedDoors = false; + Shape = RECTANGLE; + WallSquare = solidterrain(DARK_GRASS_TERRAIN), 0; + FloorSquare = solidterrain(DARK_GRASS_TERRAIN), 0; + DoorSquare = solidterrain(DARK_GRASS_TERRAIN), 0; + IsInside = false; + Flags = NO_MONSTER_GENERATION; + UseFillSquareWalls = true; + GenerateWards = false; + + Square, Pos 0, 0; + { + OTerrain = stairs(WAYPOINT_SHALLOWER) { AttachedArea = 3; AttachedEntry = WAYPOINT_DEEPER; } + EntryIndex = WAYPOINT_SHALLOWER; + } + } + + Room + { + Pos = 70:78,5:YSize-5; + Size = 1, 1; + GenerateDoor = false; + GenerateLanterns = false; + AltarPossible = false; + GenerateFountains = false; + AllowLockedDoors = false; + AllowBoobyTrappedDoors = false; + Shape = RECTANGLE; + WallSquare = solidterrain(DARK_GRASS_TERRAIN), 0; + FloorSquare = solidterrain(DARK_GRASS_TERRAIN), 0; + DoorSquare = solidterrain(DARK_GRASS_TERRAIN), 0; + IsInside = false; + Flags = NO_MONSTER_GENERATION; + UseFillSquareWalls = true; + GenerateWards = false; + + Square, Pos 0, 0; + { + OTerrain = stairs(WAYPOINT_DEEPER) { AttachedArea = 5; AttachedEntry = WAYPOINT_SHALLOWER; } + EntryIndex = WAYPOINT_DEEPER; + } + } + + Room + { + Size = 7,6; + AltarPossible = false; + DivineMaster = MELLIS; + Type = ROOM_SHOP; + GenerateFountains = false; + WallSquare = solidterrain(GRASS_TERRAIN), LIME_STONE wall(BRICK_OLD); + FloorSquare = FIR_WOOD solidterrain(PARQUET), 0; + DoorSquare = solidterrain(GRASS_TERRAIN), FIR_WOOD door; + UseFillSquareWalls = false; + GenerateDoor = true; + GenerateTunnel = false; + GenerateLanterns = true; + AllowLockedDoors = false; + AllowBoobyTrappedDoors = false; + Shape = RECTANGLE; + IsInside = true; + GenerateWindows = false; + Flags = 0; + GenerateWards = false; + + CharacterMap + { + Pos = 1, 1; + Size = 5, 4; + + Types + { + g = guard(FOREST_SHOP) { Team = 5; } + s = shopkeeper(DARK_FOREST) { Team = 5; Flags = IS_MASTER; } + } + } + { + g.s.g + ..... + ..... + g...g + } + + ItemMap + { + Pos = 1, 1; + Size = 5, 4; + + Types + { + b == Random { MinPrice = 100; MaxPrice = 10000; Category = GAUNTLET|BOOT; } + a == Random { MinPrice = 500; MaxPrice = 10000; Category = HELMET|CLOAK|BODY_ARMOR|BELT; } + d == Random { MinPrice = 200; MaxPrice = 10000; Category = RING|AMULET; } + w == Random { MinPrice = 500; MaxPrice = 10000; Category = WEAPON|SHIELD; } + e == Random { MinPrice = 50; MaxPrice = 10000; Category = FOOD|POTION; } + u == Random { MinPrice = 200; MaxPrice = 10000; Category = WAND|TOOL; } + r == Random { MinPrice = 200; MaxPrice = 10000; Category = SCROLL|BOOK; } + f == wand(WAND_OF_FIRE_BALLS); + } + } + { + .e.f. + wrwwu + uarae + .abd. + } + } + + Square, Random NOT_IN_ROOM|HAS_NO_OTERRAIN; + { + OTerrain = decoration(FIR); + Times = 600; + } + Square, Random NOT_IN_ROOM|HAS_NO_OTERRAIN; + { + OTerrain = decoration(PINE); + Times = 180; + } + Square, Random NOT_IN_ROOM|HAS_NO_OTERRAIN; + { + OTerrain = decoration(BIRCH); + Times = 120; + } + Square, Random NOT_IN_ROOM|HAS_NO_OTERRAIN; + { + OTerrain = decoration(OAK); + Times = 100; + } + + Square, Random; + { + Items == METEORIC_STEEL beartrap { Team = MONSTER_TEAM; IsActive = true; } + Times = 2:6; + } + + Square, Random NOT_IN_ROOM; + { + Character = eddy; + Times = 10; + } + } + + Level 5; /* mountain level */ + { + FillSquare = solidterrain(DARK_GRASS_TERRAIN), 0; + Size = 50, 50; + LevelMessage = "You step further inside the deep forest. In the distance you see an ominous looking rocky outcropping."; + GenerateMonsters = true; + Rooms = 3; + Items = 10:30; + IsOnGround = true; + TeamDefault = MONSTER_TEAM; + LOSModifier = 24; + IgnoreDefaultSpecialSquares = false; + CanGenerateBone = true; + BackGroundType = GREEN_FRACTAL; + DifficultyBase = 60; + IsCatacomb = false; + + RoomDefault + { + GenerateWards = false; + } + + Room /* mountain */ + { + Pos = 19, 17; + Size = 25, 25; + AllowLockedDoors = true; + AllowBoobyTrappedDoors = true; + GenerateFountains = false; + Shape = ROUND_CORNERS; + GenerateDoor = false; + GenerateLanterns = false; + AltarPossible = false; + GenerateWards = false; + WallSquare = solidterrain(DARK_GRASS_TERRAIN), 0; + FloorSquare = solidterrain(DARK_GRASS_TERRAIN), 0; + DoorSquare = solidterrain(GROUND), SAND_STONE earth; + + OTerrainMap + { + Pos = 0,0; + Size = 25,25; + Types + { + % = OBSIDIAN earth; + d = OBSIDIAN door { Parameters = LOCKED; } + } + } + { + ....%%%%%%%%%%%%%..%%%%.. + .%%%%%%%%%%%%%%%%%%%%%%%. + .%%%%%%%%%%%%%%%%%%%%%%%% + %%%%%%%%%%..%%%%%%%%%%%%. + %%%%%%%%%....%%%%%%%%%%%% + ..%%%%%%%%..%%%%%%%%%%%%% + %%%%%%%%%%%%%%%%%%%%%%%%. + %%%%%%%%%%%%%%%%%%%%%%%.. + .%%%%%%%%%%%%%%%%%%%%%... + %%%%%%%%...%%%%%%%%%%.... + %%%%%%%.....%%%%%%%%..... + .%%%%%%.....d.....d...... + %%%%%%%.....%%%%%%%%..... + %%%%%%%%...%%%%%%%%%%.... + %%%%%%%%%%%%%%%%%%%%%%... + .%%%%%%%%%%%%%%%%%%%%%%.. + ..%%%%%%%%%%%%%%%%%%%%%%. + %%%%%%%%%%%%%%%%%%%%%%%.. + %%%%%%%%%%%%%%%%%%%%%.... + .%%%%%%%%%%%%%%%%%%..%%.. + ..%%%%%%%%%%%%%%%%%...... + ..%%%%%%%%%%%%%%%%%...... + ...%%%%%%%%%%%%%%........ + ......%%%%%%%%%%%%%...... + ........%%%%%..%%%%...... + } + + GTerrainMap + { + Pos = 0,0; + Size = 25,25; + Types + { + % = LIME_STONE solidterrain(FLOOR); + _ = LIME_STONE solidterrain(FLOOR); + - = OAK_WOOD solidterrain(PARQUET); + } + } + { + ....%%%%%%%%%%%%%..%%%%.. + .%%%%%%%%%%%%%%%%%%%%%%%. + .%%%%%%%%%%%%%%%%%%%%%%%% + %%%%%%%%%%__%%%%%%%%%%%%. + %%%%%%%%%____%%%%%%%%%%%% + ..%%%%%%%%__%%%%%%%%%%%%% + %%%%%%%%%%%%%%%%%%%%%%%%. + %%%%%%%%%%%%%%%%%%%%%%%.. + .%%%%%%%%%%%%%%%%%%%%%... + %%%%%%%%___%%%%%%%%%%.... + %%%%%%%_____%%%%%%%%..... + .%%%%%%____________...... + %%%%%%%_____%%%%%%%%..... + %%%%%%%%___%%%%%%%%%%.... + %%%%%%%%%%%%%%%%%%%%%%... + .%%%%%%%%%%%%%%%%%%%%%%.. + ..%%%%%%%%%%%%%%%%%%%%%%. + %%%%%%%%%%%%%%%%%%%%%%%.. + %%%%%%%%%%%%%%%%%%%%%.... + .%%%%%%%%%%%%%%%%%%..%%.. + ..%%%%%%%%%%%%%%%%%...... + ..%%%%%%%%%%%%%%%%%...... + ...%%%%%%%%%%%%%%........ + ......%%%%%%%%%%%%%...... + ........%%%%%..%%%%...... + } + + Square, Pos 9, 12; + { + OTerrain = stairs(STAIRS_DOWN) { AttachedArea = 6; } + EntryIndex = STAIRS_DOWN; + } + + } + + /*holy shrine number 2*/ + Room + { + Pos = 2:XSize-9,2:YSize-9; + Size = 6:8, 6:8; + AllowLockedDoors = false; + AllowBoobyTrappedDoors = false; + Shape = ROUND_CORNERS; + WallSquare = solidterrain(DARK_GRASS_TERRAIN), 0; + FloorSquare = solidterrain(DARK_GRASS_TERRAIN), 0; + DoorSquare = solidterrain(DARK_GRASS_TERRAIN), 0; + GenerateDoor = false; + GenerateLanterns = false; + AltarPossible = false; + GenerateWards = true; + IsInside = false; + Flags = NO_MONSTER_GENERATION; + UseFillSquareWalls = true; + + Square, Random; + { + OTerrain = BASALT altar; + }/* + Square, Random; + { + Items == wand; + } + Square, Random; + { + Items == scroll; + Times = 2; + }*/ + Square, Random; + { + Items == Random { MinPrice = 100; Chance = 50; } + Times = 4; + } + Square, Random; + { + Items == lantern; + Times = 2; + } + } + + Square, Pos 2,25; + { + OTerrain = stairs(WAYPOINT_SHALLOWER) { AttachedArea = 4; AttachedEntry = WAYPOINT_DEEPER; } + EntryIndex = WAYPOINT_SHALLOWER; + } + + Square, Pos 47,25; + { + OTerrain = stairs(WAYPOINT_DEEPER) { AttachedArea = 8; AttachedEntry = WAYPOINT_SHALLOWER; } + EntryIndex = WAYPOINT_DEEPER; /*STAIRS_DOWN + 1;*/ + } + + Square, Random NOT_IN_ROOM|HAS_NO_OTERRAIN; + { + OTerrain = decoration(FIR); + Times = 300; + } + Square, Random NOT_IN_ROOM|HAS_NO_OTERRAIN; + { + OTerrain = decoration(PINE); + Times = 90; + } + Square, Random NOT_IN_ROOM|HAS_NO_OTERRAIN; + { + OTerrain = decoration(BIRCH); + Times = 45; + } + Square, Random NOT_IN_ROOM|HAS_NO_OTERRAIN; + { + OTerrain = decoration(OAK); + Times = 15; + } + } + + Level 6; /* 'Catacomb' style level */ + { + FillSquare = solidterrain(GROUND), OBSIDIAN earth; + TunnelSquare = solidterrain(GROUND), 0; + LevelMessage = "It is very dark and smells musty here."; + /*Description = "Haunted Lair";*/ + ShortDescription = "DF Cave"; + Size = 36, 64; + Rooms = 12:16; + IsOnGround = false; + LOSModifier = 16; + BackGroundType = GRAY_FRACTAL; + CanGenerateBone = true; + IsCatacomb = true; + GenerateMonsters = true; + TeamDefault = MONSTER_TEAM; + IgnoreDefaultSpecialSquares = false; + MonsterGenerationIntervalBase = 100; + Items = 10:15; + + RoomDefault + { + Pos = 5:XSize-10,5:YSize-10; + Size = 5:8,5:8; + WallSquare = solidterrain(GROUND), GRANITE wall(BRICK_OLD); + FloorSquare = FIR_WOOD solidterrain(PARQUET), 0; + DoorSquare = FIR_WOOD solidterrain(PARQUET), FIR_WOOD door; + GenerateTunnel = true; + GenerateWards = true; + AltarPossible = true; + GenerateDoor = true; + DivineMaster = 0; + GenerateLanterns = true; + Type = ROOM_NORMAL; + GenerateFountains = true; + AllowLockedDoors = true; + AllowBoobyTrappedDoors = true; + Shape = RECTANGLE; + IsInside = true; + GenerateWindows = false; + UseFillSquareWalls = false; + Flags = 0; + } + + Room + { + Size = 7,7; + AltarPossible = false; + AllowLockedDoors = false; + Shape = ROUND_CORNERS; + + CharacterMap + { + Pos = 1,1; + Size = 5,5; + + Types + { + f = bunny(BABY_FEMALE); + m = bunny(BABY_MALE); + F = bunny(ADULT_FEMALE); + M = bunny(ADULT_MALE); + V = vampire { Inventory = { 3, scrollofenchantweapon, scrollofenchantarmor, solstone; } } + } + } + { + .fff. + mF.Fm + mFVFm + fMFMf + .mmm. + } + } + + Square, Random; + { + Items == can { SecondaryMaterial = BANANA_FLESH; } + Times = 2; + } + + Square, Random NOT_IN_ROOM|HAS_NO_OTERRAIN; + { + OTerrain = stairs(STAIRS_UP) { AttachedArea = 5; AttachedEntry = STAIRS_DOWN; } + EntryIndex = STAIRS_UP; + } + + Square, Random NOT_IN_ROOM|HAS_NO_OTERRAIN; + { + OTerrain = stairs(STAIRS_DOWN) { AttachedArea = 7; } + EntryIndex = STAIRS_DOWN; + } + + } + + Level 7; /* Morbe's level */ + { + FillSquare = solidterrain(GROUND), OBSIDIAN earth; + TunnelSquare = solidterrain(GROUND), 0; + LevelMessage = "You smell the stench of all the world's pestillence."; + Description = "Morbe's Abode"; + /*ShortDescription = "DF Cave";*/ + Size = 40, 24; + Rooms = 1; + IsOnGround = false; + LOSModifier = 16; + BackGroundType = GRAY_FRACTAL; + AutoReveal = false; + CanGenerateBone = false; + IsCatacomb = false; + Items = 0; + GenerateMonsters = false; + TeamDefault = MONSTER_TEAM; + IgnoreDefaultSpecialSquares = false; + MonsterAmountBase = 0; + MonsterAmountDelta = 0; + MonsterGenerationIntervalBase = 0; + MonsterGenerationIntervalDelta = 0; + DifficultyBase = 30; + DifficultyDelta = 5; + + RoomDefault + { + Pos = 5:XSize-15,5:YSize-15; + Size = 5:10,5:10; + WallSquare = solidterrain(GROUND), GRANITE wall(BRICK_OLD); + FloorSquare = LIME_STONE solidterrain(GROUND), 0; + DoorSquare = LIME_STONE solidterrain(GROUND), GRANITE door; + GenerateTunnel = false; + GenerateWards = false; + AltarPossible = false; + GenerateDoor = false; + GenerateLanterns = false; + Type = ROOM_NORMAL; + GenerateFountains = false; + AllowLockedDoors = false; + AllowBoobyTrappedDoors = false; + Shape = RECTANGLE; + IsInside = true; + GenerateWindows = false; + UseFillSquareWalls = true; + Flags = NO_MONSTER_GENERATION; + } + + Room + { + Pos = 15,7; + Size = 9,9; + DivineMaster = SCABIES; + GenerateWards = false; + + OTerrainMap + { + Pos = 1,1; + Size = 7,7; + Types + { + _ = 0; + # = 0; + $ = TIN wall(BRICK_OLD); + ^ = decoration(HOLY_TREE); + c = decoration(COUCH); + d = OAK_WOOD door; + A = BLACK_DIAMOND altar(SCABIES); + } + } + { + ...A... + ....... + ....... + ....... + ....... + ....... + ....... + } + + CharacterMap + { + Pos = 1,1; + Size = 7,7; + Types + { + # = 0; + X = morbe { Team = MORBE_TEAM; } + } + } + { + ....... + ..X.... + ....... + ....... + ....... + ....... + ....... + } + + ItemMap + { + Pos = 1,1; + Size = 7,7; + Types + { + C == COPPER OMMEL_BLOOD cauldron; + } + } + { + ....... + ....C.. + ....... + ....... + ....... + ....... + ....... + } + + Square, Pos = 4, 6; + { + OTerrain = stairs(STAIRS_UP) { AttachedArea = 6; AttachedEntry = STAIRS_DOWN; } + EntryIndex = STAIRS_UP; + } + } + } + + Level 8; /* The bridge level */ + { + FillSquare = solidterrain(DARK_GRASS_TERRAIN), 0; + Size = 60, 30; + LevelMessage = "You step further inside the deep forest"; + GenerateMonsters = true; + Rooms = 1; + Items = 5:10; + IsOnGround = true; + TeamDefault = MONSTER_TEAM; + LOSModifier = 24; + IgnoreDefaultSpecialSquares = false; + CanGenerateBone = true; + BackGroundType = GREEN_FRACTAL; + DifficultyBase = 70; + DifficultyDelta = 0; + MonsterAmountBase = 21; + MonsterGenerationIntervalBase = 80; + MonsterGenerationIntervalDelta = 0; + IsCatacomb = false; + + RoomDefault + { + Pos = 36:50,1:20; + Size = 4:6,4:6; + AltarPossible = false; + WallSquare = WATER liquidterrain(POOL), 0; + FloorSquare = WATER liquidterrain(POOL), 0; + DoorSquare = solidterrain(GRASS_TERRAIN), FIR_WOOD door; + GenerateDoor = false; + DivineMaster = 0; + GenerateTunnel = false; + GenerateLanterns = false; + Type = ROOM_NORMAL; + GenerateFountains = false; + AllowLockedDoors = false; + AllowBoobyTrappedDoors = true; + Shape = RECTANGLE; + IsInside = true; + GenerateWindows = false; + UseFillSquareWalls = false; + Flags = 0; + } + + Room + { + Pos = 20:XSize-20,1; + Size = 1,1; + WallSquare = WATER liquidterrain(POOL), 0; + GenerateLanterns = false; + GenerateWindows = false; + AllowLockedDoors = false; + AllowBoobyTrappedDoors = false; + GenerateFountains = false; + AltarPossible = false; + GenerateDoor = false; + GenerateLanterns = false; + + OTerrainMap + { + Pos = 0,-1; + Size = 15,30; + Types + { + $ = GRANITE wall(BRICK_OLD); + } + } + { + ............... + ............... + ............... + ............... + ............... + ............... + ............... + ............... + ............... + ............... + ............... + ............... + ............... + ............... + ............... + ....$$$$$$$.... + ............... + ............... + ....$$$$$$$.... + ............... + ............... + ............... + ............... + ............... + ............... + ............... + ............... + ............... + ............... + ............... + } + + GTerrainMap + { + Pos = 0,-1; + Size = 15,30; + Types + { + # = WATER liquidterrain(POOL); + B = FIR_WOOD solidterrain(PARQUET); + } + } + { + #####.......... + .#####......... + ..#####........ + ...#####....... + ...#####....... + ...#####....... + ..#####........ + .#####......... + .#####......... + ..#####........ + ..#####........ + ...#####....... + ...#####....... + ....#####...... + .....#####..... + .....#####..... + ....BBBBBBB.... + ....BBBBBBB.... + .....#####..... + .....#####..... + ....#####...... + ...#####....... + ...#####....... + ...#####....... + ....#####...... + ....#####...... + ...#####....... + ...#####....... + ...#####....... + ..#####........ + } + + } + + Square, Pos 4,14; + { + OTerrain = stairs(WAYPOINT_SHALLOWER) { AttachedArea = 5; AttachedEntry = WAYPOINT_DEEPER;/* + 1; */} + EntryIndex = WAYPOINT_SHALLOWER; + } + + Square, Pos 56,20; + { + OTerrain = stairs(STAIRS_DOWN) { AttachedArea = 9; } + EntryIndex = STAIRS_DOWN; + } + + Square, Random NOT_IN_ROOM|HAS_NO_OTERRAIN; + { + OTerrain = decoration(FIR); + Times = 150; + } + Square, Random; + { + Items == METEORIC_STEEL beartrap { Team = MONSTER_TEAM; IsActive = true; } + Times = 0:3; + } + Square, Random NOT_IN_ROOM; + { + Items == STEEL beartrap { Team = MONSTER_TEAM; IsActive = true; } + Times = 0:3; + } + Square, Random NOT_IN_ROOM; + { + Items == ADAMANT beartrap { Team = MONSTER_TEAM; IsActive = true; } + Times = 0:1; + } + Square, Random NOT_IN_ROOM|HAS_NO_OTERRAIN; + { + OTerrain = decoration(BIRCH); + Times = 50; + } + Square, Random NOT_IN_ROOM|HAS_NO_OTERRAIN; + { + OTerrain = decoration(OAK); + Times = 20; + } + } + + Level 9; /* Underground Passage */ + { + FillSquare = solidterrain(GROUND), OBSIDIAN earth; + TunnelSquare = solidterrain(GROUND), 0; + /*Description = "Underground Passage";*/ + ShortDescription = "DF Passage"; + Size = 54, 54; + Rooms = 8:12; + Items = 5:10; + IsOnGround = false; + LOSModifier = 16; + BackGroundType = GRAY_FRACTAL; + CanGenerateBone = true; + IsCatacomb = false; + GenerateMonsters = true; + TeamDefault = MONSTER_TEAM; + IgnoreDefaultSpecialSquares = false; + MonsterAmountBase = 24; + MonsterGenerationIntervalBase = 60; + DifficultyBase = 90; + + RoomDefault + { + Pos = 2:XSize-10,2:YSize-10; + Size = 5:8,5:8; + WallSquare = solidterrain(GROUND), GRANITE wall(BRICK_OLD); + FloorSquare = FIR_WOOD solidterrain(PARQUET), 0; + DoorSquare = FIR_WOOD solidterrain(PARQUET), FIR_WOOD door; + GenerateTunnel = true; + GenerateWards = false; + AltarPossible = true; + GenerateDoor = true; + DivineMaster = 0; + GenerateLanterns = true; + Type = ROOM_NORMAL; + GenerateFountains = true; + AllowLockedDoors = true; + AllowBoobyTrappedDoors = true; + Shape = RECTANGLE; + IsInside = true; + GenerateWindows = false; + UseFillSquareWalls = false; + Flags = 0; + } + + Room + { + Size = 7,7; + AltarPossible = false; + AllowLockedDoors = false; + Shape = ROUND_CORNERS; + + CharacterMap + { + Pos = 1,1; + Size = 5,5; + + Types + { + a = alchemist; + w = warlock; + s = shaman; + } + } + { + ..... + .awa. + .s.s. + .awa. + ..... + } + } + + Room + { + Size = 6,6; + AltarPossible = false; + AllowLockedDoors = false; + Shape = ROUND_CORNERS; + + ItemMap + { + Pos = 1,1; + Size = 4,4; + + Types + { + a == Random { MinPrice = 40; MaxPrice = 400; Category = HELMET|CLOAK|BODY_ARMOR; } + w == Random { MinPrice = 20; MaxPrice = 500; Category = WEAPON; } + } + } + { + .aa. + waaw + wwww + .ww. + } + } + + Square, Random NOT_IN_ROOM|HAS_NO_OTERRAIN; + { + OTerrain = stairs(STAIRS_UP) { AttachedArea = 8; AttachedEntry = STAIRS_DOWN; } + EntryIndex = STAIRS_UP; + } + + Square, Random NOT_IN_ROOM|HAS_NO_OTERRAIN; + { + OTerrain = stairs(STAIRS_UP) { AttachedArea = 10; AttachedEntry = STAIRS_UP; } + EntryIndex = STAIRS_UP + 1; + } + } + + Level 10; /* Prison Level */ + { + FillSquare = solidterrain(DARK_GRASS_TERRAIN), 0; + Size = 48, 48; + LevelMessage = "You sneak into the prison within the deep forest. You enter through the sewer, (ugh)."; + Description = "the deep forest Prison level"; + ShortDescription = "DF Prison"; + GenerateMonsters = true; + Rooms = 1; + Items = 1:5; + IsOnGround = true; + TeamDefault = MONSTER_TEAM; + LOSModifier = 32; + IgnoreDefaultSpecialSquares = false; + CanGenerateBone = false; + BackGroundType = GREEN_FRACTAL; + DifficultyBase = 70; + DifficultyDelta = 0; + MonsterAmountBase = 40; + MonsterAmountDelta = 0; + MonsterGenerationIntervalBase = 60; + MonsterGenerationIntervalDelta = 0; + IsCatacomb = false; + + RoomDefault + { + Pos = 2:36,2:36; + Size = 4:6,4:6; + AltarPossible = false; + WallSquare = solidterrain(GRASS_TERRAIN), wall(BRICK_OLD); + FloorSquare = FIR_WOOD solidterrain(PARQUET), 0; + DoorSquare = solidterrain(GRASS_TERRAIN), FIR_WOOD door; + GenerateDoor = false; + DivineMaster = 0; + GenerateTunnel = false; + GenerateLanterns = false; + Type = ROOM_NORMAL; + GenerateFountains = false; + AllowLockedDoors = true; + AllowBoobyTrappedDoors = false; + Shape = RECTANGLE; + IsInside = true; + GenerateWindows = false; + UseFillSquareWalls = false; + Flags = 0; + + } + + Room /* PRISON */ + { + Pos = 7,3; + Size = 34, 23; + WallSquare = solidterrain(GRASS_TERRAIN), GRANITE wall(BRICK_OLD); + FloorSquare = FIR_WOOD solidterrain(PARQUET), 0; + GenerateLanterns = true; + GenerateWindows = false; + AllowLockedDoors = true; + AllowBoobyTrappedDoors = true; + GenerateFountains = false; + AltarPossible = false; + GenerateDoor = false; + GenerateLanterns = false; + Flags = NO_MONSTER_GENERATION; + + OTerrainMap + { + Pos = 0,0; + Size = 34,23; + Types + { + # = 0; + $ = GRANITE wall(BRICK_OLD); + % = OCTIRON wall(BRICK_OLD); + d = FIR_WOOD door; + D = STEEL door(PENTAGONAL_LOCK) { Parameters = LOCKED; } + f = fountain; + b = STEEL barwall; + @ = STEEL door(BARDOOR|PENTAGONAL_LOCK) { Parameters = LOCKED; } + B = STEEL brokendoor(BARDOOR); + k = OCTIRON barwall; + } + } + { + $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ + $%%%%%%%...$$$$$$$$$$$$$.......$.$ + $%..%..%$$$$..$..$..$..$$$%%%%%%$$ + $%..%..D...$..$..$..$..$$$%....%.$ + $%%%%%%%...$b@$bB$b@$b@$$$%....%.$ + $%..%..D..................D....%.$ + $%..%..k..................%....%.$ + $%%D%%%%.....$b@$b@$b@$bB$%%%%%%.$ + $.$.......$..$..$..$..$..$$$$$$$.$ + $.$.......$..$..$..$..$..$$....$.$ + $$$$$$$$$$$..$$$$$$$$$$$$$$$$$$$$$ + $.$.....$......................$.$ + $.$.....$......................$.$ + $.$.....d......................$.$ + $.$.....$.....$.$.$.$..........$.$ + $.$.....$....$$$$$$$$....$.....$.$ + $.$.....$....$.$.$.$.....$.....$.$ + $.$$$$$$$................$..f..$.$ + $.$.....d................$.....$.$ + $.$.....$................$.....$.$ + $$$$$$$$$$$$$$$$d$$$$$$$$$$$$$$$$$ + $.$............$.$.............$.$ + $$$$$$$$$$$$$$$$d$$$$$$$$$$$$$$$$$ + } + + CharacterMap + { + Pos = 0,0; + Size = 34, 23; + Types + { + _ = 0; + $ = 0; + % = 0; + b = 0; + B = 0; + d = 0; + D = 0; + @ = 0; + k = 0; + o = orc(OFFICER); + j = goblin(JAILER); + W = goblin(PRISON_WARDEN); + m = mistress { Team = NEW_ATTNAM_TEAM; } + w = werewolfwolf { Team = NEW_ATTNAM_TEAM; } + c = chameleon { Team = NEW_ATTNAM_TEAM; } + s = slave(DARK_FOREST) { Team = NEW_ATTNAM_TEAM; } + S = femaleslave(NEW_ATTNAM) { Team = NEW_ATTNAM_TEAM; } + F = forestman(ROVER) { Team = NEW_ATTNAM_TEAM; } + C = dog; + H = housewife(DARK_FOREST) {Team = FORESTMAN_TEAM;} + M = mangogrower {Team = NEW_ATTNAM_TEAM;} + } + } + { + $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ + $%%%%%%%...$$$$$$$$$$$$$.......$.$ + $%..%w.%$$$$H.$..$s.$M.$$$%%%%%%$$ + $%..%..D..j$..$..$..$..$$$%....%.$ + $%%%%%%%...$b@$bB$b@$b@$$$%....%.$ + $%c.%m.D..................D....%.$ + $%..%..k.................j%....%.$ + $%%D%%%%.....$b@$b@$b@$bB$%%%%%%.$ + $.$.......$..$..$..$..$..$$$$$$$.$ + $.$.j.....$..$.S$.s$C.$..$$....$.$ + $$$$$$$$$$$..$$$$$$$$$$$$$$$$$$$$$ + $.$.....$......................$.$ + $.$.....$......................$.$ + $.$.j...d......................$.$ + $.$.....$.....$.$.$.$..........$.$ + $.$.....$....$$$$$$$$....$.....$.$ + $.$..W..$....$.$.$.$.....$.....$.$ + $.$$$$$$$................$.....$.$ + $.$.....d................$.....$.$ + $.$.....$................$.....$.$ + $$$$$$$$$$$$$$$$d$$$$$$$$$$$$$$$$$ + $.$............$.$.............$.$ + $$$$$$$$$$$$$$$$d$$$$$$$$$$$$$$$$$ + } + + ItemMap + { + Pos = 0,0; + Size = 34,23; + Types + { + $ == 0; + % == 0; + b == bone; + s == skull; + B == backpack; + C == TIN itemcontainer(SMALL_CHEST) { Parameters = ~LOCKED; ItemsInside = { 1, key(PENTAGONAL_LOCK); } } + 2 == lantern { SquarePosition = DOWN; } + 3 == lantern { SquarePosition = RIGHT; } + 4 == lantern { SquarePosition = LEFT; } + 5 == lantern { SquarePosition = UP; } + a == Random { MinPrice = 40; MaxPrice = 80; Category = HELMET|CLOAK|BODY_ARMOR; } + w == Random { MinPrice = 20; MaxPrice = 60; Category = WEAPON; } + c == constitution; + M == mangoseedling; + } + } + { + $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ + $%%%%%%%...$$$$$$$$$$$$$..b....$.$ + $%.b%..%$2$$..$b.$..$..$$$%%%%%%$$ + $%s.%......$..$..$..$..$$$%M..c%.$ + $%%%%%%%...2..$..$..$..$2$%....%.$ + $%..%..........................%.$ + $%..%.....................%...B%.$ + $%%.%%%%.....$..5..$..$..$%%%%%%.$ + $.$.......$..$..$..$b.$..$$$$$$$.$ + $.$.......$..$..$..$.s$..$$....$.$ + $$$$$$5$$$$..$$$2$$$$$$$$2$$$$$$$$ + $.$.....$......................$.$ + $.$.....$......................$.$ + $.4............................$s$ + $.$.....$.....$.$.$.5..........$.$ + $.$.....4....$$$$$$$$....3.....4.$ + $b$C....$....$.$.$.$.....$.....$.$ + $.$$$$$$$................$.....$.$ + $b$aw.a..................$.....$.$ + $.$.aw.w$................$.....$.$ + $$$$$$$$$$$$5$$$.$$$$5$$$$$$$$$$$$ + $.$....s...b...$.$......b..b...$.$ + $$$$$$$$$$$$$$$$.$$$$$$$$$$$$$$$$$ + } + } + + Square, Pos 35, 21; /*entry via the sewer, no returns */ + { + EntryIndex = STAIRS_UP; + } + +/* this works, for posterity + Square, Pos 5,5; + { + OTerrain = stairs(STAIRS_UP) { AttachedArea = 9; AttachedEntry = STAIRS_UP + 1; } + EntryIndex = STAIRS_UP; + }*/ + + Square, Random NOT_IN_ROOM; + { + Character = goblin(BERSERKER); + Times = 8; + } + Square, Random NOT_IN_ROOM; + { + Character = goblin(BUTCHER); + Times = 4; + } + Square, Random NOT_IN_ROOM; + { + Character = orc(SLAUGHTERER); + Times = 4; + } + Square, Random NOT_IN_ROOM; + { + Character = orc(SQUAD_LEADER); + Times = 2; + } + Square, Random NOT_IN_ROOM; + { + Character = orc; + Times = 12; + } + Square, Random NOT_IN_ROOM; + { + Character = orc(OFFICER); + Times = 1; + } + Square, Random NOT_IN_ROOM; + { + Character = bat; + Times = 2; + } + Square, Random NOT_IN_ROOM; + { + Character = magpie; + Times = 2; + } + Square, Random NOT_IN_ROOM; + { + Character = kobold(LORD); + Times = 12; + } + + Square, Random NOT_IN_ROOM|HAS_NO_OTERRAIN; + { + OTerrain = decoration(FIR); + Times = 100; + } + Square, Random NOT_IN_ROOM|HAS_NO_OTERRAIN; + { + OTerrain = decoration(BIRCH); + Times = 30; + } + Square, Random NOT_IN_ROOM|HAS_NO_OTERRAIN; + { + OTerrain = decoration(OAK); + Times = 10; + } + } +} diff --git a/Script/dungeons/dragontower.dat b/Script/dungeons/dragontower.dat new file mode 100644 index 0000000..49ac248 --- /dev/null +++ b/Script/dungeons/dragontower.dat @@ -0,0 +1,74 @@ +Dungeon DRAGON_TOWER; +{ + Levels = 2; + + Level 0; + { + LevelMessage = "Please end my suffering"; + Description = "Dragon Tower"; + ShortDescription = "DT1"; + FillSquare = solidterrain(GRASS_TERRAIN), 0; + Size = 30, 30; + GenerateMonsters = false; + Rooms = 1; + Items = 0; + IsOnGround = true; + TeamDefault = MONSTER_TEAM; + LOSModifier = 48; + IgnoreDefaultSpecialSquares = false; + AutoReveal = true; + CanGenerateBone = false; + DifficultyBase = 50; + DifficultyDelta = 0; + EnchantmentMinusChanceBase = -15; + EnchantmentMinusChanceDelta = 0; + EnchantmentPlusChanceBase = 0; + EnchantmentPlusChanceDelta = 0; + BackGroundType = GREEN_FRACTAL; + + RoomDefault + { + Pos = 2:36,2:36; + Size = 4:6,4:6; + AltarPossible = false; + WallSquare = solidterrain(GRASS_TERRAIN), wall(BRICK_OLD); + FloorSquare = MARBLE solidterrain(PARQUET), 0; + DoorSquare = solidterrain(GRASS_TERRAIN), BALSA_WOOD door; + GenerateDoor = false; + DivineMaster = 0; + GenerateTunnel = false; + GenerateLanterns = false; + Type = ROOM_NORMAL; + GenerateFountains = false; + AllowLockedDoors = false; + AllowBoobyTrappedDoors = false; + Shape = ROUND_CORNERS; + IsInside = true; + GenerateWindows = false; + UseFillSquareWalls = false; + Flags = 0; + GenerateWards = false; + } + + Room + { + Pos = 7,7; + Size = 15,15; + AltarPossible = false; + GenerateFountains = false; + Shape = ROUND_CORNERS; + + Square, Pos 7,7; + { + OTerrain = stairs(STAIRS_UP); + EntryIndex = STAIRS_UP; + } + } + + Square, Random NOT_IN_ROOM|HAS_NO_OTERRAIN; + { + OTerrain = decoration(FIR); + Times = 50; + } + } +} diff --git a/Script/dungeons/mondedr.dat b/Script/dungeons/mondedr.dat index 27a8328..a7d761d 100644 --- a/Script/dungeons/mondedr.dat +++ b/Script/dungeons/mondedr.dat @@ -13,7 +13,7 @@ Dungeon MONDEDR; Rooms = 40; Items = 0; IsOnGround = false; - TeamDefault = MONDEDR_TEAM; //ATTNAM_TEAM; + TeamDefault = ATTNAM_TEAM; LOSModifier = 16; IgnoreDefaultSpecialSquares = false; CanGenerateBone = false; @@ -117,13 +117,13 @@ Dungeon MONDEDR; Square, Random NOT_IN_ROOM; { - Character = farmer; + Character = farmer(MONDEDR); Times = 5; } Square, Random NOT_IN_ROOM; { - Character = housewife; + Character = housewife(MONDEDR); Times = 5; } @@ -205,11 +205,12 @@ Dungeon MONDEDR; GTerrainMap { Pos = 0,0; - Size = 30,16; + Size = 30,46; Types { # = EBONY_WOOD solidterrain(FLOOR) { IsInside = true; } - = 0; + ~ = GRASS solidterrain(GROUND) { IsInside = true; } } } { @@ -229,17 +230,47 @@ Dungeon MONDEDR; #------------#--#------------# #------------#--#------------# ############################## + ..............~~.............. + ..............~~.............. + ..............~~.............. + ..............~~.............. + ..............~~.............. + ..............~~.............. + ............~~~~~~~~~~........ + ...........~~.~~....~~........ + ..........~~..~~.....~........ + .........~~...~~.....~~~~..... + .......~~.....~~.....~..~~~... + .......~......~~......~...~~.. + .....~~.......~~.......~...~.. + ..~~~..~......~~......~....~.. + ....~...~.....~~.......~...... + ....~....~....~~.....~........ + ...~....~~....~~......~....... + ..~~~~~~~~....~~.....~~~...... + ..~...~~.....~~.........~~.... + ..~.....~~....~~........~~.... + ..~~..........~~.........~~... + ..~~..........~~.........~.... + ....~.........~~.........~.... + ...~..........~~.....~~~~..... + ...~..........~~.....~..~..... + ...~..........~~....~~...~~~.. + ..............~~....~...~~.... + ..............~~...~.....~.... + ..............~~.............. + ..............~~.............. } OTerrainMap { Pos = 0,0; - Size = 30,16; + Size = 30,46; Types { # = EBONY_WOOD wall(BRICK_FINE); - - = 0; + - = 0; | = decoration(CARPET); D = EBONY_WOOD door(HEXAGONAL_LOCK); } @@ -261,17 +292,48 @@ Dungeon MONDEDR; #------------#--#------------# #------------#--#------------# ##############DD############## + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + } CharacterMap { Pos = 0,0; - Size = 30,16; + Size = 30,46; Types { # = 0; - - = 0; + - = 0; g = guard(MONDEDR_GUARD); } } @@ -292,6 +354,36 @@ Dungeon MONDEDR; #------------#--#------------# #g----------g#--#g----------g# ############################## + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. + .............................. } Square, Pos 6,10; @@ -564,7 +656,7 @@ Dungeon MONDEDR; Square, Random; { Character = rogue { Team = MONSTER_TEAM; } - Times = 5; + Times = 1; } Square, Random; @@ -593,7 +685,7 @@ Dungeon MONDEDR; Square, Random; { Character = rogue { Team = MONSTER_TEAM; } - Times = 6; + Times = 2; } Square, Random; @@ -622,7 +714,7 @@ Dungeon MONDEDR; Square, Random; { Character = rogue { Team = MONSTER_TEAM; } - Times = 7; + Times = 3; } Square, Random; @@ -634,7 +726,7 @@ Dungeon MONDEDR; Square, Random; { Items == Random { MinPrice = 500; MaxPrice = 2000; } - Times = 10; + Times = 10; } Square, Random NOT_WALKABLE|ATTACHABLE; @@ -931,6 +1023,7 @@ Dungeon MONDEDR; { Pos = 0,0; Size = 45, 54; + Types { * == 0; diff --git a/Script/dungeons/muntuo.dat b/Script/dungeons/muntuo.dat index c8e4983..a9511a8 100644 --- a/Script/dungeons/muntuo.dat +++ b/Script/dungeons/muntuo.dat @@ -227,7 +227,6 @@ Dungeon MUNTUO; Times = 1:2; } -/* Square, Random NOT_IN_ROOM; { Character = okapi { Team = SOLICITUS_TEAM; } @@ -237,7 +236,6 @@ Dungeon MUNTUO; { Character = firefox { Team = SOLICITUS_TEAM; } } -*/ Square, Pos 25, 41; { diff --git a/Script/dungeons/xinrochtomb.dat b/Script/dungeons/xinrochtomb.dat new file mode 100644 index 0000000..c89641d --- /dev/null +++ b/Script/dungeons/xinrochtomb.dat @@ -0,0 +1,74 @@ +Dungeon XINROCH_TOMB; +{ + Levels = 2; + + Level 0; + { + LevelMessage = "Please end my suffering also"; + Description = "Tomb of Xinroch"; + ShortDescription = "TX"; + FillSquare = solidterrain(GRASS_TERRAIN), 0; + Size = 30, 30; + GenerateMonsters = false; + Rooms = 1; + Items = 0; + IsOnGround = true; + TeamDefault = ATTNAM_TEAM; + LOSModifier = 48; + IgnoreDefaultSpecialSquares = false; + AutoReveal = false; + CanGenerateBone = false; + DifficultyBase = 50; + DifficultyDelta = 0; + EnchantmentMinusChanceBase = -15; + EnchantmentMinusChanceDelta = 0; + EnchantmentPlusChanceBase = 0; + EnchantmentPlusChanceDelta = 0; + BackGroundType = GREEN_FRACTAL; + + RoomDefault + { + Pos = 2:36,2:36; + Size = 4:6,4:6; + AltarPossible = false; + WallSquare = solidterrain(GRASS_TERRAIN), wall(BRICK_OLD); + FloorSquare = MARBLE solidterrain(PARQUET), 0; + DoorSquare = solidterrain(GRASS_TERRAIN), BALSA_WOOD door; + GenerateDoor = false; + DivineMaster = 0; + GenerateTunnel = false; + GenerateLanterns = false; + Type = ROOM_NORMAL; + GenerateFountains = false; + AllowLockedDoors = false; + AllowBoobyTrappedDoors = false; + Shape = ROUND_CORNERS; + IsInside = true; + GenerateWindows = false; + UseFillSquareWalls = false; + Flags = 0; + GenerateWards = false; + } + + Room + { + Pos = 7,7; + Size = 15,15; + AltarPossible = false; + GenerateFountains = false; + Shape = ROUND_CORNERS; + + Square, Pos 7,7; + { + OTerrain = stairs(STAIRS_UP); + EntryIndex = STAIRS_UP; + } + } + + Square, Random NOT_IN_ROOM|HAS_NO_OTERRAIN; + { + OTerrain = decoration(FIR); + Times = 50; + } + } +} diff --git a/Script/item_11.dat b/Script/item_11.dat index c7980fb..fbd8e92 100644 --- a/Script/item_11.dat +++ b/Script/item_11.dat @@ -49,3 +49,132 @@ mangoseedling HasSecondaryMaterial = false; IsValuable = true; } + +holymango +{ + WeaponCategory = BLUNT_WEAPONS; + Possibility = 2; + Category = FOOD; + DefaultMainVolume = 250; + StrengthModifier = 150; + FormModifier = 250; + DefaultSize = 30; + Price = 1000; + Adjective = "holy"; + NameSingular = "mango"; + NamePlural = "mangoes"; + PostFix = "of Oren Ordent"; + ArticleMode = FORCE_THE; + IsPolymorphable = false; + Roundness = 90; + BitmapPos = 0, 432; + CanBePiled = false; + CanBeBroken = false; + MainMaterialConfig == HOLY_MANGO_FLESH; + BaseEmitation = rgb24(160, 140, 110); + WieldedBitmapPos = 176, 144; + CanBeCloned = false; + CanBeMirrored = false; + AllowEquip = true; + IsValuable = true; + AttachedGod = SILVA; +} + +locationmap +{ + Category = SCROLL; + DefaultMainVolume = 250; + StrengthModifier = 25; + BitmapPos = 32, 448; + FormModifier = 20; + DefaultSize = 30; + NameSingular = "map"; + MainMaterialConfig == PARCHMENT; + IsAbstract = true; + Roundness = 15; + WieldedBitmapPos = 176, 144; + AllowEquip = false; + TeleportPriority = 300; +} + +maptotombofxinroch /* locationmap-> */ +{ + Possibility = 0; + Price = 50; + PostFix = "to the Tomb of Xinroch"; + AttachedGod = SOPHOS; + ReadDifficulty = 50; + CanBeWished = false; + CanBeCloned = false; + IsPolymorphSpawnable = false; +} + +cauldron /* materialcontainer-> */ +{ + Possibility = 0; + Category = POTION; + StrengthModifier = 350; + DefaultSize = 150; + DefaultMainVolume = 800000; + WeaponCategory = BLUNT_WEAPONS; + /*Category = POTION;*/ + DefaultSecondaryVolume = 26000; + BitmapPos = 32, 432; + /*FormModifier = 25;*/ + NameSingular = "cauldron"; + MainMaterialConfig == COPPER; + SecondaryMaterialConfig = { 11, WATER, HEALING_LIQUID, OMMEL_URINE, POISON_LIQUID, VALDEMAR, ANTIDOTE_LIQUID, VODKA, TROLL_BLOOD, OMMEL_SWEAT, OMMEL_TEARS, SULPHURIC_ACID; } + MaterialConfigChances = { 11, 75, 50, 5, 50, 2, 10, 5, 25, 5, 5, 25; } + Roundness = 100; + CanBeBroken = false; + AttachedGod = NONE; + WieldedBitmapPos = 176, 144; + IsValuable = false; + TeleportPriority = 200; + ThrowItemTypes = THROW_POTION; + CanBeGeneratedInContainer = false; + CanBePickedUp = false; +} + +kleinbottle /* materialcontainer-> */ +{ + DefaultSize = 30; + Possibility = 0; + WeaponCategory = BLUNT_WEAPONS; + Category = POTION; + DefaultMainVolume = 60; + DefaultSecondaryVolume = 1000; + StrengthModifier = 50; + BitmapPos = 80, 464; + FormModifier = 25; + NameSingular = "klein bottle"; + MainMaterialConfig == GLASS; + SecondaryMaterialConfig == WATER; + /*MaterialConfigChances == 0;*/ + /*Alias = { 2, "potion", "drink"; }*/ + Roundness = 70; + CanBeBroken = false; + AttachedGod = SOPHOS; + WieldedBitmapPos = 176, 144; + IsValuable = true; + TeleportPriority = 200; + CanBeCloned = false; + CanBeMirrored = true; + IsQuestItem = true; + CanBeWished = false; + IsMaterialChangeable = true; + IsPolymorphSpawnable = false; + IsPolymorphable = false; +} + +scrolloffireballs /* scroll-> */ +{ + Possibility = 15; + Price = 1000; + PostFix = "of fireballs"; + Alias == "sofb"; + AttachedGod = LEGIFER; + ReadDifficulty = 1000; + IsPolymorphSpawnable = false; + CanBeCloned = false; +} diff --git a/src/game/char.cpp b/src/game/char.cpp index 7cea8a1..6b1fce1 100644 --- a/src/game/char.cpp +++ b/src/game/char.cpp @@ -1352,6 +1352,61 @@ truth character::HasGoldenEagleShirt () const { } +truth character::HasOmmelBlood () const { + for (stackiterator i = GetStack()->GetBottom(); i.HasItem(); ++i) + if (i->IsKleinBottle() && i->GetSecondaryMaterial() && i->GetSecondaryMaterial()->GetConfig() == OMMEL_BLOOD) return true; + // + for (int c = 0; c < GetEquipments(); ++c) { + item *Item = GetEquipment(c); + // + if (Item && Item->IsKleinBottle() && Item->GetSecondaryMaterial() && Item->GetSecondaryMaterial()->GetConfig() == OMMEL_BLOOD) return true; + } + return false; //combineequipmentpredicates()(this, &item::IsKleinBottle, 1); +} + + +truth character::CurdleOmmelBlood () const { + for (stackiterator i = GetStack()->GetBottom(); i.HasItem(); ++i) { + if (i->IsKleinBottle() && i->GetSecondaryMaterial() && i->GetSecondaryMaterial()->GetConfig() == OMMEL_BLOOD) { + i->ChangeSecondaryMaterial(MAKE_MATERIAL(CURDLED_OMMEL_BLOOD)); + return true; + } + } + // + for (int c = 0; c < GetEquipments(); ++c) { + item *Item = GetEquipment(c); + // + if (Item && Item->IsKleinBottle() && Item->GetSecondaryMaterial() && Item->GetSecondaryMaterial()->GetConfig() == OMMEL_BLOOD) { + Item->ChangeSecondaryMaterial(MAKE_MATERIAL(CURDLED_OMMEL_BLOOD)); + return true; + } + } + return false; //combineequipmentpredicates()(this, &item::IsKleinBottle, 1); +} + + +truth character::RemoveCurdledOmmelBlood () { + for (stackiterator i = GetStack()->GetBottom(); i.HasItem(); ++i) { + if (i->IsKleinBottle() && i->GetSecondaryMaterial() && i->GetSecondaryMaterial()->GetConfig() == CURDLED_OMMEL_BLOOD) { + (*i)->RemoveFromSlot(); + (*i)->SendToHell(); + return true; + } + } + // + for (int c = 0; c < GetEquipments(); ++c) { + item *Item = GetEquipment(c); + // + if (Item && Item->IsKleinBottle() && Item->GetSecondaryMaterial() && Item->GetSecondaryMaterial()->GetConfig() == CURDLED_OMMEL_BLOOD) { + Item->RemoveFromSlot(); + Item->SendToHell(); + return true; + } + } + return false; +} + + int character::GeneralRemoveItem (ItemCheckerCB chk, truth allItems) { truth done; int cnt = 0; diff --git a/src/game/char.h b/src/game/char.h index 2104244..316d6ab 100644 --- a/src/game/char.h +++ b/src/game/char.h @@ -307,6 +307,10 @@ public: truth HasHeadOfElpuri () const; truth HasGoldenEagleShirt () const; truth HasPetrussNut () const; + truth HasCurdledBlood() const; + truth HasOmmelBlood() const; + truth CurdleOmmelBlood() const; + truth RemoveCurdledOmmelBlood(); truth RemoveEncryptedScroll (); truth RemoveMondedrPass (); truth RemoveRingOfThieves (); diff --git a/src/game/confdef.h b/src/game/confdef.h index a64609c..95d1fae 100644 --- a/src/game/confdef.h +++ b/src/game/confdef.h @@ -401,6 +401,9 @@ #define ELDER 3 #define ARCH_MAGE 4 +#define ROVER 1 +#define BAND_LEADER 2 + #define FIELD_MOUSE 1 #define LABORATORY_MOUSE 2 @@ -408,6 +411,8 @@ #define STARVED_OX 1 +#define FLOATIE 1 + /* Least significant bit defines sex */ #define BABY_MALE 2 diff --git a/src/game/game.cpp b/src/game/game.cpp index 7119fba..473224c 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -53,8 +53,8 @@ #define SAVE_FILE_VERSION 119 // Increment this if changes make savefiles incompatible #define BONE_FILE_VERSION 106 // Increment this if changes make bonefiles incompatible */ -#define SAVE_FILE_VERSION 124 // Increment this if changes make savefiles incompatible -#define BONE_FILE_VERSION 109 // Increment this if changes make bonefiles incompatible +#define SAVE_FILE_VERSION 125 // Increment this if changes make savefiles incompatible +#define BONE_FILE_VERSION 110 // Increment this if changes make bonefiles incompatible #define LOADED 0 #define NEW_GAME 1 @@ -98,6 +98,8 @@ int game::Masamune; int game::Muramasa; int game::LoricatusHammer; int game::Liberator; +int game::OmmelBloodMission; +int game::RegiiTalkState; /* */ massacremap game::PlayerMassacreMap; massacremap game::PetMassacreMap; @@ -389,6 +391,8 @@ truth game::Init (cfestring &Name) { Muramasa = 0; LoricatusHammer = 0; Liberator = 0; + OmmelBloodMission = 0; + RegiiTalkState = 0; /* */ PlayerMassacreMap.clear(); PetMassacreMap.clear(); @@ -773,6 +777,7 @@ truth game::Save (cfestring &SaveName) { SaveFile << AveragePlayerAgilityExperience; SaveFile << Teams << Dungeons << StoryState << PlayerRunning; SaveFile << MondedrPass << RingOfThieves << Masamune << Muramasa << LoricatusHammer << Liberator; + SaveFile << OmmelBloodMission << RegiiTalkState; SaveFile << PlayerMassacreMap << PetMassacreMap << MiscMassacreMap; SaveFile << PlayerMassacreAmount << PetMassacreAmount << MiscMassacreAmount; SaveArray(SaveFile, EquipmentMemory, MAX_EQUIPMENT_SLOTS); @@ -823,12 +828,8 @@ int game::Load (cfestring &SaveName) { SaveFile >> AveragePlayerDexterityExperience; SaveFile >> AveragePlayerAgilityExperience; SaveFile >> Teams >> Dungeons >> StoryState >> PlayerRunning; - SaveFile >> MondedrPass >> RingOfThieves >> Masamune >> Muramasa >> LoricatusHammer; - if (Version == SAVE_FILE_VERSION) { - SaveFile >> Liberator; - } else { - Liberator = 0; - } + SaveFile >> MondedrPass >> RingOfThieves >> Masamune >> Muramasa >> LoricatusHammer >> Liberator; + SaveFile >> OmmelBloodMission >> RegiiTalkState; SaveFile >> PlayerMassacreMap >> PetMassacreMap >> MiscMassacreMap; SaveFile >> PlayerMassacreAmount >> PetMassacreAmount >> MiscMassacreAmount; LoadArray(SaveFile, EquipmentMemory, MAX_EQUIPMENT_SLOTS); diff --git a/src/game/game.h b/src/game/game.h index f2b6654..12bd7c7 100644 --- a/src/game/game.h +++ b/src/game/game.h @@ -343,6 +343,10 @@ public: static void SetLoricatusHammer (int What) { LoricatusHammer = What; } static int GetLiberator () { return Liberator; } static void SetLiberator (int What) { Liberator = What; } + static int GetOmmelBloodMission() { return OmmelBloodMission; } + static void SetOmmelBloodMission(int What) { OmmelBloodMission = What; } + static int GetRegiiTalkState() { return RegiiTalkState; } + static void SetRegiiTalkState(int What) { RegiiTalkState = What; } static void SetIsInGetCommand(truth What) { InGetCommand = What; } static truth IsInGetCommand() { return InGetCommand; } static festring GetHomeDir(); @@ -542,6 +546,8 @@ private: static int Muramasa; static int LoricatusHammer; static int Liberator; + static int OmmelBloodMission; + static int RegiiTalkState; static truth InGetCommand; static truth PlayerHurtByExplosion; static area* CurrentArea; diff --git a/src/game/gears/meleeweapon_taiaha.cpp b/src/game/gears/meleeweapon_taiaha.cpp dissimilarity index 65% index c0b8233..bcf8986 100644 --- a/src/game/gears/meleeweapon_taiaha.cpp +++ b/src/game/gears/meleeweapon_taiaha.cpp @@ -1,204 +1,165 @@ -#ifdef HEADER_PHASE -ITEM(taiaha, meleeweapon) -{ - public: - //virtual truth HitEffect(character*, character*, v2, int, int, truth); - //virtual void BlockEffect(character*, character*, item*, int Type); - virtual truth AllowAlphaEverywhere() const { return true; } - virtual void Save(outputfile&) const; - virtual void Load(inputfile&); - virtual void ChargeFully(character*) { TimesUsed = 0; } - virtual truth IsAppliable(ccharacter*) const { return false; } - virtual truth IsZappable(ccharacter*) const { return true; } - virtual truth IsChargeable(ccharacter*) const { return true; } - virtual truth ReceiveDamage(character*, int, int, int); - virtual truth Zap(character*, v2, int); - virtual void AddInventoryEntry(ccharacter*, festring&, int, truth) const; //this? - virtual truth IsExplosive() const { return true; } - protected: - virtual int GetClassAnimationFrames() const; - virtual col16 GetOutlineColor(int) const; - virtual alpha GetOutlineAlpha(int) const; - virtual void PostConstruct(); - void BreakEffect(character*, cfestring&); - //feuLong GetSpecialParameters() const; - int Charges; - int TimesUsed; -}; - - -#else - - - -int taiaha::GetClassAnimationFrames() const { return !IsBroken() ? 128 : 1; } - - - -truth taiaha::Zap(character* Zapper, v2, int Direction) -{ - if(Charges <= TimesUsed) - { - ADD_MESSAGE("Nothing happens."); - return true; - } - - Zapper->EditExperience(PERCEPTION, 150, 1 << 10); - int TaiahaBeamEffect = RAND() & 3; - - beamdata Beam // Just hard-code this - ( - Zapper, - CONST_S("killed by ") + GetName(INDEFINITE) + " zapped @bk", - Zapper->GetPos(), - GREEN, //was GetBeamColor() - TaiahaBeamEffect ? ((RAND() & 2) ? BEAM_FIRE_BALL : BEAM_STRIKE ) : BEAM_LIGHTNING, //was GetBeamEffect() - Direction, - 15, // 10 is the lowest beamrange out of the three - 0 //was GetSpecialParameters() - ); - - (GetLevel()->*level::GetBeam(!TaiahaBeamEffect))(Beam); // BeamStyle = !TaiahaBeamEffect; - ++TimesUsed; - return true; -} - - - -void taiaha::AddInventoryEntry(ccharacter* Viewer, festring& Entry, int, truth ShowSpecialInfo) const // never piled -{ - AddName(Entry, INDEFINITE); - - if(ShowSpecialInfo) - { - Entry << " [" << GetWeight() << "g, DAM " << GetBaseMinDamage() << '-' << GetBaseMaxDamage(); - Entry << ", " << GetBaseToHitValueDescription(); - - if(!IsBroken() && !IsWhip()) - Entry << ", " << GetStrengthValueDescription(); - - int CWeaponSkillLevel = Viewer->GetCWeaponSkillLevel(this); - int SWeaponSkillLevel = Viewer->GetSWeaponSkillLevel(this); - - if(CWeaponSkillLevel || SWeaponSkillLevel) - Entry << ", skill " << CWeaponSkillLevel << '/' << SWeaponSkillLevel; - - if(TimesUsed == 1) - Entry << ", zapped 1 time]"; - else if(TimesUsed) - Entry << ", zapped " << TimesUsed << " times]"; - else - Entry << "]"; - } -} - - - -void taiaha::BreakEffect(character* Terrorist, cfestring& DeathMsg) -{ - v2 Pos = GetPos(); - level* Level = GetLevel(); - RemoveFromSlot(); - feuLong StackSize = Level->AddRadiusToSquareStack(Pos, 2); //hardcode, default is 2 for most wands, but zero for fireballs - lsquare** SquareStack = Level->GetSquareStack(); - - for (unsigned int c = 0; c < StackSize; ++c) SquareStack[c]->RemoveFlags(IN_SQUARE_STACK); - - fearray Stack(SquareStack, StackSize); - (Level->*level::GetBeamEffectVisualizer(PARTICLE_BEAM))(Stack, YELLOW); //beamstyle - - beamdata Beam - ( - Terrorist, - DeathMsg, - YOURSELF, - 0 //was GetSpecialParameters() - ); - - for (unsigned int c = 0; c < Stack.Size; ++c) (Stack[c]->*lsquare::GetBeamEffect(BEAM_FIRE_BALL))(Beam); // beam effect - - SendToHell(); //removes the taiaha from existence -} - - - -void taiaha::Save(outputfile& SaveFile) const -{ - item::Save(SaveFile); - SaveFile << TimesUsed << Charges; - SaveFile << Enchantment; - SaveFile << SecondaryMaterial; - //meleeweapon::Save(SaveFile); -} - - - -void taiaha::Load(inputfile& SaveFile) -{ - item::Load(SaveFile); - SaveFile >> TimesUsed >> Charges; - SaveFile >> Enchantment; - LoadMaterial(SaveFile, SecondaryMaterial); - //meleeweapon::Load(SaveFile); -} - - - -truth taiaha::ReceiveDamage(character* Damager, int Damage, int Type, int) -{ - if(Type & (FIRE|ENERGY|PHYSICAL_DAMAGE) && Damage && (Damage > 125 || !(RAND() % (250 / Damage)))) - { - festring DeathMsg = CONST_S("killed by an explosion of "); - AddName(DeathMsg, INDEFINITE); - - if(Damager) - DeathMsg << " caused @bk"; - - if(CanBeSeenByPlayer()) - ADD_MESSAGE("%s %s.", GetExtendedDescription().CStr(), GetBreakMsg().CStr()); - - BreakEffect(Damager, DeathMsg); - return true; - } - - return false; -} - - - -void taiaha::PostConstruct() -{ - Charges = GetMinCharges() + RAND() % (GetMaxCharges() - GetMinCharges() + 1); - TimesUsed = 0; - meleeweapon::PostConstruct(); -} - - - -alpha taiaha::GetOutlineAlpha(int Frame) const -{ - if(!IsBroken()) - { - Frame &= 31; - return Frame * (31 - Frame) >> 1; - } - else - return 255; -} - - - -col16 taiaha::GetOutlineColor(int Frame) const -{ - if(!IsBroken()) - switch((Frame&127) >> 5) - { - case 0: return BLUE; - case 1: return GREEN; - case 2: return RED; - case 3: return YELLOW; - } - - return TRANSPARENT_COLOR; -} -#endif +#ifdef HEADER_PHASE +ITEM(taiaha, meleeweapon) +{ +public: + taiaha () : Charges(0), TimesUsed(0) {} + + //virtual truth HitEffect(character*, character*, v2, int, int, truth); + //virtual void BlockEffect(character*, character*, item*, int Type); + virtual truth AllowAlphaEverywhere () const { return true; } + virtual void Save (outputfile &) const; + virtual void Load (inputfile &); + virtual void ChargeFully (character *) { TimesUsed = 0; } + virtual truth IsAppliable(ccharacter *) const { return false; } + virtual truth IsZappable (ccharacter *) const { return true; } + virtual truth IsChargeable (ccharacter *) const { return true; } + virtual truth ReceiveDamage (character *, int, int, int); + virtual truth Zap (character *, v2, int); + virtual void AddInventoryEntry (ccharacter *, festring &, int, truth) const; //this? + virtual truth IsExplosive () const { return true; } + +protected: + virtual int GetClassAnimationFrames () const; + virtual col16 GetOutlineColor (int) const; + virtual alpha GetOutlineAlpha (int) const; + virtual void PostConstruct (); + void BreakEffect (character *, cfestring &); + //feuLong GetSpecialParameters () const; + +protected: + int Charges; + int TimesUsed; +}; + + +#else + + +int taiaha::GetClassAnimationFrames () const { return !IsBroken() ? 128 : 1; } + + +void taiaha::Save (outputfile &SaveFile) const { + meleeweapon::Save(SaveFile); + SaveFile << TimesUsed << Charges; +} + + +void taiaha::Load (inputfile &SaveFile) { + meleeweapon::Load(SaveFile); + SaveFile >> TimesUsed >> Charges; +} + + +truth taiaha::Zap (character *Zapper, v2, int Direction) { + if (Charges <= TimesUsed) { + ADD_MESSAGE("Nothing happens."); + return true; + } + // + Zapper->EditExperience(PERCEPTION, 150, 1 << 10); + int TaiahaBeamEffect = RAND()&3; + // + // Just hard-code this + beamdata Beam ( + Zapper, + CONST_S("killed by ") + GetName(INDEFINITE) + " zapped @bk", + Zapper->GetPos(), + GREEN, //was GetBeamColor() + TaiahaBeamEffect ? ((RAND() & 2) ? BEAM_FIRE_BALL : BEAM_STRIKE ) : BEAM_LIGHTNING, //was GetBeamEffect() + Direction, + 15, // 10 is the lowest beamrange out of the three + 0 //was GetSpecialParameters() + ); + (GetLevel()->*level::GetBeam(!TaiahaBeamEffect))(Beam); // BeamStyle = !TaiahaBeamEffect; + ++TimesUsed; + return true; +} + + +// never piled +void taiaha::AddInventoryEntry (ccharacter *Viewer, festring& Entry, int, truth ShowSpecialInfo) const { + AddName(Entry, INDEFINITE); + if (ShowSpecialInfo) { + Entry << " [" << GetWeight() << "g, DAM " << GetBaseMinDamage() << '-' << GetBaseMaxDamage(); + Entry << ", " << GetBaseToHitValueDescription(); + if (!IsBroken() && !IsWhip()) Entry << ", " << GetStrengthValueDescription(); + // + int CWeaponSkillLevel = Viewer->GetCWeaponSkillLevel(this); + int SWeaponSkillLevel = Viewer->GetSWeaponSkillLevel(this); + // + if (CWeaponSkillLevel || SWeaponSkillLevel) Entry << ", skill " << CWeaponSkillLevel << '/' << SWeaponSkillLevel; + if (TimesUsed == 1) Entry << ", zapped 1 time]"; + else if (TimesUsed) Entry << ", zapped " << TimesUsed << " times]"; + else Entry << "]"; + } +} + + +void taiaha::BreakEffect (character *Terrorist, cfestring &DeathMsg) { + v2 Pos = GetPos(); + level *Level = GetLevel(); + // + RemoveFromSlot(); + feuLong StackSize = Level->AddRadiusToSquareStack(Pos, 2); //hardcode, default is 2 for most wands, but zero for fireballs + lsquare **SquareStack = Level->GetSquareStack(); + // + for (unsigned int c = 0; c < StackSize; ++c) SquareStack[c]->RemoveFlags(IN_SQUARE_STACK); + // + fearray Stack(SquareStack, StackSize); + (Level->*level::GetBeamEffectVisualizer(PARTICLE_BEAM))(Stack, YELLOW); //beamstyle + // + beamdata Beam ( + Terrorist, + DeathMsg, + YOURSELF, + 0 //was GetSpecialParameters() + ); + for (unsigned int c = 0; c < Stack.Size; ++c) (Stack[c]->*lsquare::GetBeamEffect(BEAM_FIRE_BALL))(Beam); // beam effect + SendToHell(); //removes the taiaha from existence +} + + +truth taiaha::ReceiveDamage (character *Damager, int Damage, int Type, int) { + if (Type & (FIRE|ENERGY|PHYSICAL_DAMAGE) && Damage && (Damage > 125 || !(RAND()%(250/Damage)))) { + festring DeathMsg = CONST_S("killed by an explosion of "); + // + AddName(DeathMsg, INDEFINITE); + if (Damager) DeathMsg << " caused @bk"; + if (CanBeSeenByPlayer()) ADD_MESSAGE("%s %s.", GetExtendedDescription().CStr(), GetBreakMsg().CStr()); + BreakEffect(Damager, DeathMsg); + return true; + } + return false; +} + + +void taiaha::PostConstruct () { + Charges = GetMinCharges()+RAND()%(GetMaxCharges()-GetMinCharges()+1); + TimesUsed = 0; + meleeweapon::PostConstruct(); +} + + +alpha taiaha::GetOutlineAlpha (int Frame) const { + if (!IsBroken()) { + Frame &= 31; + return Frame*(31-Frame)>>1; + } + return 255; +} + + +col16 taiaha::GetOutlineColor (int Frame) const { + if (!IsBroken()) { + switch ((Frame&127)>>5) { + case 0: return BLUE; + case 1: return GREEN; + case 2: return RED; + case 3: return YELLOW; + } + } + return TRANSPARENT_COLOR; +} + + +#endif diff --git a/src/game/humans/humanoid_UTFAOfficial.cpp b/src/game/humans/humanoid_UTFAOfficial.cpp new file mode 100644 index 0000000..71c8974 --- /dev/null +++ b/src/game/humans/humanoid_UTFAOfficial.cpp @@ -0,0 +1,7 @@ +#ifdef HEADER_PHASE +CHARACTER(UTFAOfficial, humanoid) +{ +public: + virtual void GetAICommand () { StandIdleAI(); } +}; +#endif diff --git a/src/game/humans/humanoid_ennerbeast.cpp b/src/game/humans/humanoid_ennerbeast.cpp index 065d908..1fcc71b 100644 --- a/src/game/humans/humanoid_ennerbeast.cpp +++ b/src/game/humans/humanoid_ennerbeast.cpp @@ -49,6 +49,10 @@ truth ennerbeast::Hit(character* Enemy, v2, int, int) Char->ReceiveDamage(this, ScreamStrength, SOUND, ALL, YOURSELF, true); Char->CheckDeath(CONST_S("killed @bkp scream"), this); msgsystem::LeaveBigMessageMode(); + + if (Char->IsPlayer() && Char->HasOmmelBlood() && CanBeSeenByPlayer()) { + if (Char->CurdleOmmelBlood()) ADD_MESSAGE("Your vial of Ommel Blood vibrates and it contents curdles with the scream of the Enner Beast."); + } } GetNearLSquare(x, y)->GetStack()->ReceiveDamage(this, ScreamStrength, SOUND); diff --git a/src/game/humans/humanoid_forestman.cpp b/src/game/humans/humanoid_forestman.cpp new file mode 100644 index 0000000..2b11eb6 --- /dev/null +++ b/src/game/humans/humanoid_forestman.cpp @@ -0,0 +1,26 @@ +#ifdef HEADER_PHASE +CHARACTER(forestman, humanoid) +{ +public: + virtual character *GetLeader() const; + +protected: + virtual void GetAICommand (); +}; + + +#else + + +character *forestman::GetLeader () const { + character *Guide = game::GetTeam(FORESTMAN_TEAM)->GetLeader(); + return Guide && Guide->GetRelation(this) != HOSTILE ? Guide : GetTeam()->GetLeader(); +} + + +void forestman::GetAICommand () { + humanoid::GetAICommand(); +} + + +#endif diff --git a/src/game/humans/humanoid_kabouter.cpp b/src/game/humans/humanoid_kabouter.cpp new file mode 100644 index 0000000..f724954 --- /dev/null +++ b/src/game/humans/humanoid_kabouter.cpp @@ -0,0 +1,125 @@ +#ifdef HEADER_PHASE +CHARACTER(kabouter, humanoid) +{ +public: + kabouter() : LastTamed(0) {} + + virtual void Load(inputfile &); + virtual void Save(outputfile &) const; + //virtual int GetAttribute (int, truth = true) const; + virtual void FinalProcessForBone (); + +protected: + virtual void GetAICommand (); + int GetSpellAPCost () const; + +protected: + ulong LastTamed; +}; + + +#else + + +void kabouter::Save (outputfile &SaveFile) const { + humanoid::Save(SaveFile); + SaveFile << LastTamed; +} + + +void kabouter::Load (inputfile &SaveFile) { + humanoid::Load(SaveFile); + SaveFile >> LastTamed; +} + + +void kabouter::FinalProcessForBone() +{ + humanoid::FinalProcessForBone(); + LastTamed = 0; +} + + +void kabouter::GetAICommand () { + SeekLeader(GetLeader()); + if (FollowLeader(GetLeader())) return; + // + character *NearestEnemy = 0; + sLong NearestEnemyDistance = 0x7FFFFFFF; + v2 Pos = GetPos(); + // + for (int c = 0; c < game::GetTeams(); ++c) { + if (GetTeam()->GetRelation(game::GetTeam(c)) == HOSTILE) { + for (std::list::const_iterator i = game::GetTeam(c)->GetMember().begin(); i != game::GetTeam(c)->GetMember().end(); ++i) { + if ((*i)->IsEnabled()) { + sLong ThisDistance = Max(abs((*i)->GetPos().X - Pos.X), abs((*i)->GetPos().Y - Pos.Y)); + // + if ((ThisDistance < NearestEnemyDistance || (ThisDistance == NearestEnemyDistance && !(RAND()%3))) && (*i)->CanBeSeenBy(this)) { + NearestEnemy = *i; + NearestEnemyDistance = ThisDistance; + } + } + } + } + } + // + if (NearestEnemy && (NearestEnemyDistance < 10 || StateIsActivated(PANIC)) && (RAND()&3)) { + SetGoingTo((Pos << 1)-NearestEnemy->GetPos()); + if (MoveTowardsTarget(true)) return; + } + // + if ((/*LastTamed &&*/ game::GetTick()-LastTamed < 100) && NearestEnemy && NearestEnemyDistance < 2) { + // how about LastTamed < 500 + //do nothing, otherwise do the charming + } else if (NearestEnemy) { + LastTamed = game::GetTick(); + for (int d = 0; d < GetNeighbourSquares(); ++d) { + square *Square = GetNeighbourSquare(d); + // + if (Square) { + character *Char = Square->GetCharacter(); + if (Char) { + if (!Char->IsPlayer() /*&& (GetRelation(Char) == HOSTILE)*/) { + //check the creature's hostility at this point + if (CanBeSeenByPlayer()) { + if (PLAYER->CanHear()) ADD_MESSAGE("%s whispers mesmerizing spells.", CHAR_NAME(DEFINITE)); + else ADD_MESSAGE("You see %s mouthing mesmerizing spells.", CHAR_NAME(DEFINITE)); + } + if (Char->CanHear()) { + if (Char->CanTameWithLyre(this)) { + //if(Char->GetTeam() == GetTeam() && Char->CanBeSeenByPlayer()) ADD_MESSAGE("%s seems to be very happy.", Char->CHAR_NAME(DEFINITE)); else + if (Char->GetRelation(this) == HOSTILE && Char->CanBeSeenByPlayer()) { + ADD_MESSAGE("%s stops fighting.", Char->CHAR_NAME(DEFINITE)); + if (Char->CanBeSeenByPlayer()) ADD_MESSAGE("%s seems to be very friendly towards %s.", Char->CHAR_NAME(DEFINITE), CHAR_NAME(DEFINITE)); + } + Char->ChangeTeam(GetTeam()); + } else if (Char->CanBeSeenByPlayer()) { + ADD_MESSAGE("%s resists %s's charming spells.", Char->CHAR_NAME(DEFINITE), CHAR_NAME(DEFINITE)); + } + } else if (Char->CanBeSeenByPlayer()) { + ADD_MESSAGE("%s seems not affected.", Char->CHAR_NAME(DEFINITE)); + } + } + } + } + } + EditAP(-1000); + game::CallForAttention(GetPos(), 100); + return; + } + // + if (CheckAIZapOpportunity()) return; + if (CheckForUsefulItemsOnGround()) return; + if (CheckForDoors()) return; + if (CheckSadism()) return; + if (MoveRandomly()) return; + EditAP(-1000); +} + + +int kabouter::GetSpellAPCost () const { + return 4000; +} + + +#endif diff --git a/src/game/humans/humanoid_morbe.cpp b/src/game/humans/humanoid_morbe.cpp new file mode 100644 index 0000000..47253a6 --- /dev/null +++ b/src/game/humans/humanoid_morbe.cpp @@ -0,0 +1,124 @@ +#ifdef HEADER_PHASE +CHARACTER(morbe, humanoid) +{ +public: + virtual void BeTalkedTo (); + //virtual void FinalProcessForBone (); + //virtual truth MoveTowardsHomePos (); // may need this in times to come + +protected: + virtual void CreateCorpse (lsquare *); + virtual void GetAICommand (); + +protected: + //ulong LastHealed; +}; + + +#else + + +void morbe::GetAICommand () { + StandIdleAI(); +} + + +void morbe::CreateCorpse (lsquare *Square) { + angel *Angel; + int Seen = 0; + // + for (int c = 0; c < 3; ++c) { + if (!c) Angel = archangel::Spawn(SCABIES); else Angel = angel::Spawn(SCABIES); + // + v2 Where = game::GetCurrentLevel()->GetRandomSquare(Angel); + // + Angel->SetTeam(game::GetTeam(4)); + Angel->PutTo(Where); + if (Angel->CanBeSeenByPlayer()) ++Seen; + } + // + if (Seen == 1) ADD_MESSAGE("%s materializes.", Angel->CHAR_NAME(INDEFINITE)); + else if (Seen == 2) ADD_MESSAGE("Two %s materialize.", Angel->CHAR_NAME(PLURAL)); + else if (Seen == 3) ADD_MESSAGE("Three %s materialize.", Angel->CHAR_NAME(PLURAL)); + ADD_MESSAGE("\"We will defend the Unholy Order!\""); + SendToHell(); +} + + +void morbe::BeTalkedTo () { + if (GetRelation(PLAYER) == HOSTILE) { + ADD_MESSAGE("A plague on all your household!"); + return; + } + // + if (PLAYER->HasCurdledBlood()) { + if (PLAYER->RemoveCurdledOmmelBlood()) { + game::TextScreen(CONST_S( + "You hand over the vial filled with curdled ommel blood. Morbe is delighted.\n" + "\"You have retrieved the curdled ommel blood!\n" + "I will share a little of my knowledge with you, as a gift.\"")); + game::TextScreen(CONST_S( + "Morbe begins to relate a dark secret to you from the depths of her knowledge:\n" + "\"There is a place not far from here, a place of utter darkness\n" + "where dwells the soul of the ancient Warlord Xinroch.\n" + "His bones have long since departed that place, but his soul still dwells beneath.\n" + "It is stirring as we speak.\"")); + /* + game::LoadWorldMap(); + v2 XinrochTombPos = game::GetWorldMap()->GetEntryPos(0, XINROCH_TOMB); + game::GetWorldMap()->GetWSquare(XinrochTombPos)->ChangeOWTerrain(xinrochtomb::Spawn()); + game::GetWorldMap()->RevealEnvironment(XinrochTombPos, 1); + game::SaveWorldMap(); + */ + GetArea()->SendNewDrawRequest(); + game::SetOmmelBloodMission(2); + ADD_MESSAGE("Morbe hands you a map revealing the location of the tomb. \"There are untold riches in the Tomb of Xinroch, but beware, his many minions protect him and will kill all who attempt to enter that place!\""); + // + maptotombofxinroch *MapToTombOfXinroch = maptotombofxinroch::Spawn(); + // + MapToTombOfXinroch->MoveTo(PLAYER->GetStack()); + return; + } + } + // + if (game::GetOmmelBloodMission() != 2) { + if (!game::GetOmmelBloodMission()) { + game::TextScreen(CONST_S( + "You approach the acolyte standing by the cauldron, she speaks to you.\n\n" + "\"Welcome, ")+PLAYER->GetPanelName().CStr()+CONST_S(".\n" + "Doubtless I have seen you from afar and by the powers of the goddess,\n" + "I have drawn you here to me. Can you not feel the presence of the\n" + "unholy Scabies here in my abode? Indeed it is I, Morbe, high\n" + "priestess of Scabies, who channels the powers of the goddess\n" + "into the world above Valpurus!\"\n\n" + "You feel your stomach churn as you realise where you are, the source of all illness and\n" + "pestillence in the world. Morbe speaks further: \n\n")); + game::TextScreen(CONST_S( + "\"I have brought you here because I have a use for you. I need you to\n" + "curdle a measure of Ommel Blood with the scream of the Enner Beast!\n" + "Here is a klein bottle, it may be dipped, but not drunk from. It will\n" + "not break due to the cry of the Enner Beast. I have filled it with\n" + "the Ommel blood from this cauldron. Wield it before you as you encounter\n" + "the enner beast in person; the liquid should change noticably.\n" + "I promise you a great gift in exchange for this favour. Return\n" + "to me with this very vial, filled with curdled Ommel blood!\"")); + // + kleinbottle *KleinBottle = kleinbottle::Spawn(); + // + KleinBottle->ChangeSecondaryMaterial(MAKE_MATERIAL(OMMEL_BLOOD)); + KleinBottle->MoveTo(PLAYER->GetStack()); + GetArea()->SendNewDrawRequest(); + ADD_MESSAGE("\"Do not fail me, or the goddess will be unhappy!\""); + game::SetOmmelBloodMission(1); + } else { + /* StoryState == 1 */ + ADD_MESSAGE("Morbe says: \"Bring me the vial of curdled Ommel Blood and I'll tell you my secrets.\""); + } + } else { + /* StoryState == 2 */ + ADD_MESSAGE("Morbe says: \"I have all I need from you right now. Be gone!\""); + } +} + + +#endif diff --git a/src/game/humans/humanoid_regii.cpp b/src/game/humans/humanoid_regii.cpp new file mode 100644 index 0000000..7d8709f --- /dev/null +++ b/src/game/humans/humanoid_regii.cpp @@ -0,0 +1,58 @@ +#ifdef HEADER_PHASE +CHARACTER(regii, humanoid) +{ +public: + virtual void GetAICommand () { StandIdleAI(); } + virtual void BeTalkedTo (); + //virtual void DisplayStethoscopeInfo (character*) const; +}; + + +#else + + +void regii::BeTalkedTo () { + static sLong Said; + // + if (GetRelation(PLAYER) == HOSTILE) { + ProcessAndAddMessage(GetHostileReplies()[RandomizeReply(Said, GetHostileReplies().Size)]); + } + if (!game::GetRegiiTalkState()) { + game::TextScreen(CONST_S( + "\"I am Regii, of the Unite Tweraif Forest Army, or UTFA for short. And you are?\"\n" + "\n" + "You tell Regii your name and explain that you have escaped from New Attnam.\n")); + game::TextScreen(CONST_S("\"Do you really hate the imperialists?\"\n")); + game::TextScreen(CONST_S("\"A lot\" You reply.\n\n")); + game::TextScreen(CONST_S( + "\"Alright then. From now on, you shall be called\n'")+PLAYER->GetPanelName().CStr()+CONST_S("'\n" + " that is called '")+PLAYER->GetPanelName().CStr()+CONST_S("'.\"\n" + "Regii saluts you after the fashion of the UTFA.\n\n\n" + "\"Now, listen up! We have an upcoming mission, we will be launching a\n" + "reconaissance to free some prisoners held in the forest prison.\n" + "The prison is operated by goblins and guarded by manifold beasts and\n" + "orcs. They have no political reason to operate the prison, other than\n" + "the fact that it spins straw into gold.\n" + "We have reason to believe that the imperialists pay the goblins to\n" + "imprison our brothers and sisters of the formerly independant Tweraif.\"")); + game::TextScreen(CONST_S( + "\"Now the mission is to free the prisoners, but, our intelligence suspects\n" + "that important constitutional documents are held within the prison also.\n" + "If it is within our power to do so, these should be retrieved and safeguarded.\n" + "The assualt on the prison will be achieved by means of a haphazard underground\n" + "tunnel whose entry point is located beyond the river. The tunnel terminates\n" + "more or less underneath the prison, so that is where the assault will begin.\n" + "Free the prisoners, arm them with weapons or otherwise, and fight your way out\n" + "of the vicinity of the prison. Members will regroup here after the mission\n" + "for a de-brief.\"")); + GetArea()->SendNewDrawRequest(); + game::SetRegiiTalkState(1); + return; + } else { + //ADD_MESSAGE("\"How goes your preparation for the mission brother ") + PLAYER->GetPanelName().CStr() + CONST_S("?\""); + ProcessAndAddMessage(GetFriendlyReplies()[RandomizeReply(Said, GetFriendlyReplies().Size)]); + } +} + + +#endif diff --git a/src/game/humans/humanoid_uldra.cpp b/src/game/humans/humanoid_uldra.cpp new file mode 100644 index 0000000..d2f4066 --- /dev/null +++ b/src/game/humans/humanoid_uldra.cpp @@ -0,0 +1,130 @@ +#ifdef HEADER_PHASE +CHARACTER(uldra, humanoid) +{ +protected: + virtual void GetAICommand (); + int GetSpellAPCost () const; +}; + + +#else + + +void uldra::GetAICommand () { + SeekLeader(GetLeader()); + if (FollowLeader(GetLeader())) return; + // + character *NearestEnemy = 0; + sLong NearestEnemyDistance = 0x7FFFFFFF; + v2 Pos = GetPos(); + // + for (int c = 0; c < game::GetTeams(); ++c) { + if (GetTeam()->GetRelation(game::GetTeam(c)) == HOSTILE) { + for (std::list::const_iterator i = game::GetTeam(c)->GetMember().begin(); i != game::GetTeam(c)->GetMember().end(); ++i) { + if ((*i)->IsEnabled()) { + sLong ThisDistance = Max(abs((*i)->GetPos().X - Pos.X), abs((*i)->GetPos().Y - Pos.Y)); + // + if ((ThisDistance < NearestEnemyDistance || (ThisDistance == NearestEnemyDistance && !(RAND() % 3))) && (*i)->CanBeSeenBy(this)) { + NearestEnemy = *i; + NearestEnemyDistance = ThisDistance; + } + } + } + } + } + // + if (NearestEnemy && NearestEnemy->GetPos().IsAdjacent(Pos)) { + if (!(RAND()&3)) { + if (CanBeSeenByPlayer()) ADD_MESSAGE("%s grins at you and disappears.", CHAR_NAME(DEFINITE)); + TeleportRandomly(true); + EditAP(-GetSpellAPCost()); + return; + } else if (NearestEnemy->IsSmall() && + GetAttribute(WISDOM) < NearestEnemy->GetAttackWisdomLimit() && + !(RAND()&3) && + Hit(NearestEnemy, NearestEnemy->GetPos(), game::GetDirectionForVector(NearestEnemy->GetPos()-GetPos()))) { + return; + } + } + // + if (NearestEnemy && (NearestEnemyDistance < 10 || StateIsActivated(PANIC)) && (RAND()&3)) { + SetGoingTo((Pos<<1)-NearestEnemy->GetPos()); + if (MoveTowardsTarget(true)) return; + } + // + if (NearestEnemy) { + lsquare *Square = NearestEnemy->GetLSquareUnder(); + // + EditAP(-GetSpellAPCost()); + switch (RAND()%50) { + case 0: + case 1: + case 2: { + // + character *Buffalo = buffalo::Spawn(); + v2 Where = GetLevel()->GetNearestFreeSquare(Buffalo, Square->GetPos()); + // + if (Where == ERROR_V2) { + if (CanBeSeenByPlayer()) ADD_MESSAGE("%s grins and invokes a spell, but failed miserably.", CHAR_NAME(DEFINITE)); + delete Buffalo; + } else { + if (CanBeSeenByPlayer()) ADD_MESSAGE("%s grins and invokes a spell!", CHAR_NAME(DEFINITE)); + Buffalo->SetGenerationDanger(GetGenerationDanger()); + Buffalo->SetTeam(GetTeam()); + Buffalo->PutTo(Where); + if (Buffalo->CanBeSeenByPlayer()) ADD_MESSAGE("Suddenly %s materializes!", Buffalo->CHAR_NAME(INDEFINITE)); + Buffalo->GetLSquareUnder()->DrawParticles(RED); + } + } break; + case 3: { + if (CanBeSeenByPlayer()) ADD_MESSAGE("%s grins and invokes a spell!", CHAR_NAME(DEFINITE)); + // + character *Twoheadedmoose = twoheadedmoose::Spawn(); + v2 Where = GetLevel()->GetNearestFreeSquare(Twoheadedmoose, Square->GetPos()); + // + if (Where == ERROR_V2) { + if (CanBeSeenByPlayer()) ADD_MESSAGE("Nothing happens."); delete Twoheadedmoose; + } else { + Twoheadedmoose->SetGenerationDanger(GetGenerationDanger()); + Twoheadedmoose->SetTeam(GetTeam()); + Twoheadedmoose->PutTo(Where); + if (Twoheadedmoose->CanBeSeenByPlayer()) ADD_MESSAGE("Suddenly %s materializes!", Twoheadedmoose->CHAR_NAME(INDEFINITE)); + Twoheadedmoose->GetLSquareUnder()->DrawParticles(RED); + } + } break; + case 4: { + if (CanBeSeenByPlayer()) ADD_MESSAGE("%s grins and invokes a spell!", CHAR_NAME(DEFINITE)); + // + character *Bear = bear::Spawn(RAND() % 3 ? BLACK_BEAR : GRIZZLY_BEAR); + v2 Where = GetLevel()->GetNearestFreeSquare(Bear, Square->GetPos()); + // + if (Where == ERROR_V2) { + if (CanBeSeenByPlayer()) ADD_MESSAGE("Nothing happens."); + delete Bear; + } else { + Bear->SetGenerationDanger(GetGenerationDanger()); + Bear->SetTeam(GetTeam()); + Bear->PutTo(Where); + if (Bear->CanBeSeenByPlayer()) ADD_MESSAGE("Suddenly %s materializes!", Bear->CHAR_NAME(INDEFINITE)); + Bear->GetLSquareUnder()->DrawParticles(RED); + } + } break; + default: break; + } + return; + } + // + if (CheckForUsefulItemsOnGround()) return; + if (CheckForDoors()) return; + if (CheckSadism()) return; + if (MoveRandomly()) return; + EditAP(-1000); +} + + +int uldra::GetSpellAPCost () const { + return 4000; +} + + +#endif diff --git a/src/game/item.cpp b/src/game/item.cpp index f5fb96c..4f0201e 100644 --- a/src/game/item.cpp +++ b/src/game/item.cpp @@ -69,6 +69,7 @@ truth item::IsInCorrectSlot () const { return IsInCorrectSlot(static_cast(*Slot)->GetEquipmentIndex(); } int item::GetGraphicsContainerIndex () const { return GR_ITEM; } truth item::IsBroken () const { return GetConfig () & BROKEN; } +truth item::IsFood() const { return DataBase->Category & FOOD; } cchar *item::GetBreakVerb () const { return "breaks"; } square *item::GetSquareUnderEntity (int I) const { return GetSquareUnder(I); } square *item::GetSquareUnder (int I) const { return Slot[I] ? Slot[I]->GetSquareUnder () : 0; } diff --git a/src/game/item.h b/src/game/item.h index 9572135..70a1d5b 100644 --- a/src/game/item.h +++ b/src/game/item.h @@ -252,6 +252,7 @@ class item : public object virtual truth IsPetrussNut() const { return false; } virtual truth IsGoldenEagleShirt() const { return false; } virtual truth IsMoneyBag () const { return false; } + virtual truth IsKleinBottle () const { return false; } virtual truth CanBeRead(character*) const { return false; } virtual truth Read(character*); virtual void FinishReading(character*) { } @@ -482,6 +483,7 @@ class item : public object virtual double GetDamageBonus() const { return 0.; } virtual void DrawContents(ccharacter*) { } virtual truth IsBroken() const; + virtual truth IsFood() const; virtual int GetEnchantment() const { return 0; } sLong GetEnchantedPrice(int) const; virtual item* Fix(); @@ -612,6 +614,7 @@ class item : public object virtual truth IsBottle () const { return false; } virtual truth IsCan () const { return false; } virtual truth IsScroll () const { return false; } + virtual truth IsMango () const { return false; } protected: virtual cchar* GetBreakVerb() const; diff --git a/src/game/items/0list.cpp b/src/game/items/0list.cpp index 55c4f8e..014a342 100644 --- a/src/game/items/0list.cpp +++ b/src/game/items/0list.cpp @@ -1,3 +1,10 @@ +#ifndef HEADER_PHASE +#include "worldmap.h" +#include "wsquare.h" +#include "wterras.h" +#endif + + #include "items/item_avatarofvalpurus.cpp" #include "items/item_bananapeels.cpp" #include "items/item_bone.cpp" @@ -9,6 +16,7 @@ #include "items/item_gorovitscopyoflenin.cpp" #include "items/item_headofelpuri.cpp" #include "items/item_holyhandgrenade.cpp" +#include "items/item_holymango.cpp" #include "items/item_horn.cpp" #include "items/item_key.cpp" #include "items/item_kiwi.cpp" @@ -26,6 +34,9 @@ #include "items/item_ullrbone.cpp" #include "items/item_wand.cpp" +#include "items/item_locationmap.cpp" +#include "items/locationmap_maptotombofxinroch.cpp" + #include "items/item_mango.cpp" #include "items/item_mangoseedling.cpp" @@ -45,8 +56,11 @@ #include "items/materialcontainer_backpack.cpp" #include "items/materialcontainer_banana.cpp" #include "items/materialcontainer_can.cpp" +#include "items/materialcontainer_cauldron.cpp" #include "items/materialcontainer_gasgrenade.cpp" +#include "items/materialcontainer_kleinbottle.cpp" #include "items/materialcontainer_potion.cpp" + #include "items/lockableitem_itemcontainer.cpp" #include "items/banana_holybanana.cpp" @@ -64,6 +78,7 @@ #include "items/scroll_scrollofdetectmaterial.cpp" #include "items/scroll_scrollofenchantarmor.cpp" #include "items/scroll_scrollofenchantweapon.cpp" +#include "items/scroll_scrolloffireballs.cpp" #include "items/scroll_scrollofgolemcreation.cpp" #include "items/scroll_scrollofhardenmaterial.cpp" #include "items/scroll_scrollofrepair.cpp" diff --git a/src/game/items/holybook_celestialmonograph.cpp b/src/game/items/holybook_celestialmonograph.cpp index 90f18cb..5ec5f41 100644 --- a/src/game/items/holybook_celestialmonograph.cpp +++ b/src/game/items/holybook_celestialmonograph.cpp @@ -3,15 +3,15 @@ ITEM(celestialmonograph, holybook) { public: virtual void FinishReading (character *); + protected: - virtual col16 GetMaterialColorA(int) const; + virtual col16 GetMaterialColorA (int) const; }; #else - void celestialmonograph::FinishReading (character *Reader) { if (Reader->IsPlayer()) { PLAYER->EditExperience(INTELLIGENCE, 500, 1<<12); @@ -25,7 +25,6 @@ void celestialmonograph::FinishReading (character *Reader) { } - col16 celestialmonograph::GetMaterialColorA (int) const { return MakeRGB16(40, 140, 40); } diff --git a/src/game/items/item_holymango.cpp b/src/game/items/item_holymango.cpp new file mode 100644 index 0000000..3d0271c --- /dev/null +++ b/src/game/items/item_holymango.cpp @@ -0,0 +1,91 @@ +#ifdef HEADER_PHASE +ITEM(holymango, item) +{ +public: + virtual truth HitEffect (character *, character *, v2, int, int, truth); + //virtual truth Zap (character *, v2, int); + //virtual void Be () {} + virtual int GetSpecialFlags () const; + virtual void AddInventoryEntry (ccharacter *, festring &, int, truth) const; + virtual truth ReceiveDamage (character *, int, int, int); + virtual truth IsMango () const { return true; } +}; + + +#else + + +int holymango::GetSpecialFlags () const { return ST_FLAME_1; } + + +truth holymango::HitEffect (character *Enemy, character *Hitter, v2 HitPos, int BodyPartIndex, int Direction, truth BlockedByArmour) { + truth BaseSuccess = 1;//mango::HitEffect(Enemy, Hitter, HitPos, BodyPartIndex, Direction, BlockedByArmour); + // + if (Enemy->IsEnabled() && RAND() & 1) { + if (Enemy->IsPlayer() || Hitter->IsPlayer() || Enemy->CanBeSeenByPlayer() || Hitter->CanBeSeenByPlayer()) { + ADD_MESSAGE("%s mango burns %s.", Hitter->CHAR_POSSESSIVE_PRONOUN, Enemy->CHAR_DESCRIPTION(DEFINITE)); + } + return Enemy->ReceiveBodyPartDamage(Hitter, 2 + (RAND() & 3), FIRE, BodyPartIndex, Direction) || BaseSuccess; + } + return BaseSuccess; +} + + +/* +truth holymango::Zap (character *Zapper, v2, int Direction) { + if (Charges > TimesUsed) { + ADD_MESSAGE("BANG! You zap %s!", CHAR_NAME(DEFINITE)); + Zapper->EditExperience(PERCEPTION, 150, 1 << 10); + beamdata Beam( + Zapper, + CONST_S("killed by ") + GetName(INDEFINITE), + Zapper->GetPos(), + YELLOW, + BEAM_FIRE_BALL, + Direction, + 50, + 0 + ); + (GetLevel()->*level::GetBeam(PARTICLE_BEAM))(Beam); + ++TimesUsed; + } else { + ADD_MESSAGE("Click!"); + } + return true; +} +*/ + + +// never piled +void holymango::AddInventoryEntry (ccharacter *Viewer, festring& Entry, int, truth ShowSpecialInfo) const { + AddName(Entry, INDEFINITE); + if (ShowSpecialInfo) { + Entry << " [" << GetWeight() << "g, DAM " << GetBaseMinDamage() << '-' << GetBaseMaxDamage(); + Entry << ", " << GetBaseToHitValueDescription(); + if (!IsBroken()) Entry << ", " << GetStrengthValueDescription(); + int CWeaponSkillLevel = Viewer->GetCWeaponSkillLevel(this); + int SWeaponSkillLevel = Viewer->GetSWeaponSkillLevel(this); + if (CWeaponSkillLevel || SWeaponSkillLevel) Entry << ", skill " << CWeaponSkillLevel << '/' << SWeaponSkillLevel; + Entry << ']'; + } +} + + +truth holymango::ReceiveDamage (character *Damager, int Damage, int Type, int) { + if (Type & (PHYSICAL_DAMAGE|FIRE|ENERGY) && Damage && (Damage > 50 || !(RAND()%(100/Damage)))) { + lsquare *Square = GetLSquareUnder(); + festring DeathMsg = CONST_S("killed by an explosion of "); + // + AddName(DeathMsg, INDEFINITE); + if (Damager) DeathMsg << " caused @bk"; + if (GetSquareUnder()->CanBeSeenByPlayer(true)) ADD_MESSAGE("%s explodes!", GetExtendedDescription().CStr()); + RemoveFromSlot(); + SendToHell(); + Square->GetLevel()->Explosion(Damager, DeathMsg, Square->GetPos(), 6*50); + return true; + } + return false; +} + + +#endif diff --git a/src/game/items/item_locationmap.cpp b/src/game/items/item_locationmap.cpp new file mode 100644 index 0000000..06527ff --- /dev/null +++ b/src/game/items/item_locationmap.cpp @@ -0,0 +1,30 @@ +#ifdef HEADER_PHASE +ITEM(locationmap, item) +{ +public: + virtual truth CanBeRead (character *) const; + virtual truth IsReadable (ccharacter *) const { return true; } + virtual truth ReceiveDamage (character *, int, int, int); +}; + + +#else + + +truth locationmap::CanBeRead (character *Reader) const { + return Reader->CanRead() || game::GetSeeWholeMapCheatMode(); +} + + +truth locationmap::ReceiveDamage (character *, int Damage, int Type, int) { + if (Type & FIRE && Damage && GetMainMaterial()->GetInteractionFlags() & CAN_BURN && (Damage > 125 || !(RAND()%(250/Damage)))) { + if (CanBeSeenByPlayer()) ADD_MESSAGE("%s catches fire!", GetExtendedDescription().CStr()); + RemoveFromSlot(); + SendToHell(); + return true; + } + return false; +} + + +#endif diff --git a/src/game/items/item_mango.cpp b/src/game/items/item_mango.cpp index 4f7a9ae..55eee9d 100644 --- a/src/game/items/item_mango.cpp +++ b/src/game/items/item_mango.cpp @@ -1,5 +1,7 @@ #ifdef HEADER_PHASE ITEM(mango, item) { +public: + virtual truth IsMango () const { return true; } }; #endif diff --git a/src/game/items/locationmap_maptotombofxinroch.cpp b/src/game/items/locationmap_maptotombofxinroch.cpp new file mode 100644 index 0000000..e16ea19 --- /dev/null +++ b/src/game/items/locationmap_maptotombofxinroch.cpp @@ -0,0 +1,31 @@ +#ifdef HEADER_PHASE +ITEM(maptotombofxinroch, locationmap) +{ +public: + virtual void FinishReading (character *); +}; + + +#else + +class worldmap; + + +void maptotombofxinroch::FinishReading (character *Reader) { + if (!Reader->IsPlayer() && Reader->CanBeSeenByPlayer()) ADD_MESSAGE("%s disappears!", Reader->CHAR_NAME(DEFINITE)); + if (Reader->IsPlayer()) { + //game::RevealXinrochTomb(); + game::LoadWorldMap(); + v2 XinrochTombPos = game::GetWorldMap()->GetEntryPos(0, XINROCH_TOMB); + game::GetWorldMap()->GetWSquare(XinrochTombPos)->ChangeOWTerrain(xinrochtomb::Spawn()); + game::GetWorldMap()->RevealEnvironment(XinrochTombPos, 1); + game::SaveWorldMap(); + ADD_MESSAGE("The map reveals to you the location of the Tomb of Xinroch and burns."); + } + RemoveFromSlot(); + SendToHell(); + Reader->EditExperience(INTELLIGENCE, 150, 1 << 12); +} + + +#endif diff --git a/src/game/items/materialcontainer_can.cpp b/src/game/items/materialcontainer_can.cpp dissimilarity index 86% index 8c5ae7d..26fcdcd 100644 --- a/src/game/items/materialcontainer_can.cpp +++ b/src/game/items/materialcontainer_can.cpp @@ -1,65 +1,46 @@ -#ifdef HEADER_PHASE -ITEM(can, materialcontainer) -{ - public: - virtual item* BetterVersion() const; - virtual void DipInto(liquid*, character*); - virtual truth IsDippable(ccharacter*) const { return !SecondaryMaterial; } - virtual truth IsDipDestination(ccharacter*) const; - virtual truth IsDumpable(ccharacter*) const { return SecondaryMaterial != 0; } - virtual liquid* CreateDipLiquid(); - virtual truth AllowSpoil() const { return false; } // temporary - virtual truth Spoils() const { return false; } // temporary - virtual truth HasBetterVersion() const { return !SecondaryMaterial; } - virtual truth IsCan () const { return true; } - protected: - virtual void AddPostFix(festring& String, int) const { AddContainerPostFix(String); } - virtual truth AddAdjective(festring&, truth) const; - virtual v2 GetBitmapPos(int) const; -}; - - -#else - - - -truth can::AddAdjective(festring& String, truth Articled) const { return AddEmptyAdjective(String, Articled); } - - - -v2 can::GetBitmapPos(int) const { return v2(16, SecondaryMaterial ? 288 : 304); } - - - -truth can::IsDipDestination(ccharacter*) const { return SecondaryMaterial && SecondaryMaterial->IsLiquid(); } - - - -liquid* can::CreateDipLiquid() -{ - return static_cast(GetSecondaryMaterial()->TakeDipVolumeAway()); -} - - - -item* can::BetterVersion() const -{ - if(!GetSecondaryMaterial()) - return can::Spawn(); - else - return 0; -} - - - -void can::DipInto(liquid* Liquid, character* Dipper) -{ - /* Add alchemy */ - - if(Dipper->IsPlayer()) - ADD_MESSAGE("%s is now filled with %s.", CHAR_NAME(DEFINITE), Liquid->GetName(false, false).CStr()); - - ChangeSecondaryMaterial(Liquid); - Dipper->DexterityAction(10); -} -#endif +#ifdef HEADER_PHASE +ITEM(can, materialcontainer) +{ +public: + virtual item *BetterVersion () const; + virtual void DipInto (liquid *, character *); + virtual truth IsDippable (ccharacter *) const { return !SecondaryMaterial; } + virtual truth IsDipDestination (ccharacter *) const; + virtual truth IsDumpable (ccharacter *) const { return SecondaryMaterial != 0; } + virtual liquid *CreateDipLiquid (); + virtual truth AllowSpoil () const { return false; } // temporary + virtual truth Spoils () const { return false; } // temporary + virtual truth HasBetterVersion () const { return !SecondaryMaterial; } + virtual truth IsCan () const { return true; } + protected: + virtual void AddPostFix (festring &String, int) const { AddContainerPostFix(String); } + virtual truth AddAdjective (festring &, truth) const; + virtual v2 GetBitmapPos (int) const; +}; + + +#else + + +truth can::AddAdjective (festring &String, truth Articled) const { return AddEmptyAdjective(String, Articled); } +v2 can::GetBitmapPos (int) const { return v2(16, SecondaryMaterial ? 288 : 304); } +truth can::IsDipDestination (ccharacter *) const { return SecondaryMaterial && SecondaryMaterial->IsLiquid(); } +liquid *can::CreateDipLiquid () { return static_cast(GetSecondaryMaterial()->TakeDipVolumeAway()); } + + + +item *can::BetterVersion () const { + if (!GetSecondaryMaterial()) return can::Spawn(); + return 0; +} + + +void can::DipInto (liquid *Liquid, character *Dipper) { + /* Add alchemy */ + if (Dipper->IsPlayer()) ADD_MESSAGE("%s is now filled with %s.", CHAR_NAME(DEFINITE), Liquid->GetName(false, false).CStr()); + ChangeSecondaryMaterial(Liquid); + Dipper->DexterityAction(10); +} + + +#endif diff --git a/src/game/items/materialcontainer_cauldron.cpp b/src/game/items/materialcontainer_cauldron.cpp new file mode 100644 index 0000000..473e8ff --- /dev/null +++ b/src/game/items/materialcontainer_cauldron.cpp @@ -0,0 +1,48 @@ +#ifdef HEADER_PHASE +ITEM(cauldron, materialcontainer) +{ +public: + virtual item *BetterVersion () const; + virtual void DipInto (liquid *, character *); + virtual liquid *CreateDipLiquid (); + virtual truth IsDippable (ccharacter *) const { return !SecondaryMaterial; } + virtual truth IsDumpable (ccharacter *) const { return SecondaryMaterial != 0; } + //virtual void Break (character *, int); + virtual truth IsDipDestination (ccharacter *) const; + virtual truth IsExplosive () const; + //virtual truth ReceiveDamage (character *, int, int, int); // can't break ... unless it turns into a lump of copper?? hmmm. Maybe can have a cracked cauldron. + virtual truth HasBetterVersion () const { return !SecondaryMaterial; } + virtual truth EffectIsGood () const; + virtual truth IsKamikazeWeapon (ccharacter *) const { return IsExplosive(); } + +protected: + virtual void AddPostFix (festring &String, int) const { AddContainerPostFix(String); } + virtual truth AddAdjective (festring &, truth) const; +}; + + +#else + + +truth cauldron::IsExplosive () const { return GetSecondaryMaterial() && GetSecondaryMaterial()->IsExplosive(); } +truth cauldron::AddAdjective (festring & String, truth Articled) const { return AddEmptyAdjective(String, Articled); } +truth cauldron::EffectIsGood () const { return GetSecondaryMaterial() && GetSecondaryMaterial()->GetInteractionFlags() & EFFECT_IS_GOOD; } +truth cauldron::IsDipDestination (ccharacter *) const { return SecondaryMaterial && SecondaryMaterial->IsLiquid(); } +liquid *cauldron::CreateDipLiquid () { return static_cast(GetSecondaryMaterial()->TakeDipVolumeAway()); } + + +void cauldron::DipInto (liquid *Liquid, character *Dipper) { + /* Add alchemy */ + if (Dipper->IsPlayer()) ADD_MESSAGE("%s is now filled with %s.", CHAR_NAME(DEFINITE), Liquid->GetName(false, false).CStr()); + ChangeSecondaryMaterial(Liquid); + Dipper->DexterityAction(10); +} + + +item *cauldron::BetterVersion () const { + if (!GetSecondaryMaterial()) return cauldron::Spawn(); + return 0; +} + + +#endif diff --git a/src/game/items/materialcontainer_kleinbottle.cpp b/src/game/items/materialcontainer_kleinbottle.cpp new file mode 100644 index 0000000..3113b36 --- /dev/null +++ b/src/game/items/materialcontainer_kleinbottle.cpp @@ -0,0 +1,49 @@ +#ifdef HEADER_PHASE +ITEM(kleinbottle, materialcontainer) +{ + public: + //virtual item *BetterVersion () const; // better version is a filled version of the klein bottle + virtual void DipInto (liquid *, character *); + virtual liquid *CreateDipLiquid (); + virtual truth IsDippable (ccharacter *) const { return !SecondaryMaterial; } + virtual truth IsDumpable (ccharacter *) const { return SecondaryMaterial != 0; } + virtual material *GetConsumeMaterial (ccharacter *, materialpredicate = TrueMaterialPredicate) const; + //virtual void Break (character *, int); // cannot be broken, remove this + //virtual truth IsDipDestination (ccharacter *) const; // cannot be dipped into + //virtual truth IsExplosive () const; // cannot explode contents since the contents resides in another dimension + //virtual truth ReceiveDamage (character *, int, int, int); // should not recieve damage + //virtual truth HasBetterVersion () const { return !SecondaryMaterial; } // cannot be filled by mellis + //virtual truth EffectIsGood () const; + //virtual truth IsKamikazeWeapon (ccharacter *) const { return IsExplosive(); } // no explode, so false + virtual truth IsKleinBottle () const { return true; } + +protected: + virtual void AddPostFix (festring &String, int) const { AddContainerPostFix(String); } + virtual truth AddAdjective (festring &, truth) const; +}; + + +#else + + +truth kleinbottle::AddAdjective (festring &String, truth Articled) const { return AddEmptyAdjective(String, Articled); } +liquid *kleinbottle::CreateDipLiquid () { return static_cast(GetSecondaryMaterial()->TakeDipVolumeAway()); } + + +void kleinbottle::DipInto (liquid *Liquid, character *Dipper) { + /* Add alchemy */ + if (Dipper->IsPlayer()) ADD_MESSAGE("%s is now filled with %s.", CHAR_NAME(DEFINITE), Liquid->GetName(false, false).CStr()); + ChangeSecondaryMaterial(Liquid); + Dipper->DexterityAction(100); +} + + +material *kleinbottle::GetConsumeMaterial (ccharacter *Consumer, materialpredicate Predicate) const { + if (SecondaryMaterial && (SecondaryMaterial->*Predicate)() && Consumer->CanConsume(SecondaryMaterial) && Consumer->StateIsActivated(TELEPORT)) { + return SecondaryMaterial; + } + return item::GetConsumeMaterial(Consumer, Predicate); +} + + +#endif diff --git a/src/game/items/scroll_scrolloffireballs.cpp b/src/game/items/scroll_scrolloffireballs.cpp new file mode 100644 index 0000000..f78df0d --- /dev/null +++ b/src/game/items/scroll_scrolloffireballs.cpp @@ -0,0 +1,78 @@ +#ifdef HEADER_PHASE +ITEM(scrolloffireballs, scroll) +{ +public: + virtual void FinishReading (character *); + virtual truth IsExplosive () const { return true; } +}; + + +#else + + +void scrolloffireballs::FinishReading (character *Reader) { + v2 FireBallPos = ERROR_V2; + // + beamdata Beam( + Reader, + CONST_S("killed by the spells of ") + Reader->GetName(INDEFINITE), + YOURSELF, + 0 + ); + ADD_MESSAGE("This could be loud..."); + // + v2 Input = game::PositionQuestion(CONST_S("Where do you wish to send the fireball? [direction keys move cursor, space accepts]"), Reader->GetPos(), &game::TeleportHandler, 0, false); + // + if (Input == ERROR_V2) { + // esc pressed + ADD_MESSAGE("You choose not to summon a fireball... phew!"); + return; + } + // + lsquare *Square = GetNearLSquare(Input); + // + if ((Input - Reader->GetPos()).GetLengthSquare() <= Reader->GetTeleportRangeSquare()) { + if (!Reader->IsFreeForMe(Square) || (Input == Reader->GetPos())) { + //Reader->EditExperience(INTELLIGENCE, 100, 1 << 10); + FireBallPos = Input; + } else { + ADD_MESSAGE("The spell must target creatures, %s.", game::Insult()); + //FireBallPos = Reader->GetPos(); /*Better not. It's a little bit wtf for the player to understand*/ + return; + } + } else { + ADD_MESSAGE("You cannot concentrate yourself enough to send a fireball that far."); + //FireBallPos = ERROR_V2; + //if (Reader->GetNearestEnemy()) FireBallPos = Reader->GetNearestEnemy()->GetPos(); else + if (!(RAND()%3)) { + ADD_MESSAGE("Something very wrong happens with the spell."); + FireBallPos = Reader->GetPos(); + Square = GetNearLSquare(Reader->GetPos()); + } else { + return; + } + } + // + if (FireBallPos == ERROR_V2) Square = GetNearLSquare(GetLevel()->GetRandomSquare(Reader)); + if (Square->GetPos() == Reader->GetPos()) { + ADD_MESSAGE("The scroll explodes in your face!"); + //Square->DrawParticles(RED); + //Square->FireBall(Beam); + //if(Reader->GetAction() && Reader->GetAction()->IsVoluntary()) + // Reader->GetAction()->Terminate(false); + //RemoveFromSlot(); + //SendToHell(); + //Reader->EditExperience(INTELLIGENCE, 150, 1 << 12); + //return; + } else { //(FireBallPos != ERROR_V2) + ADD_MESSAGE("A mighty fireball is called into existence."); + } + RemoveFromSlot(); + SendToHell(); + Reader->EditExperience(INTELLIGENCE, 150, 1 << 12); + Square->DrawParticles(RED); + Square->FireBall(Beam); +} + + +#endif diff --git a/src/game/nonhumans/0list.cpp b/src/game/nonhumans/0list.cpp index b243d16..7350ae1 100644 --- a/src/game/nonhumans/0list.cpp +++ b/src/game/nonhumans/0list.cpp @@ -33,9 +33,15 @@ #include "nonhumans/nonhumanoid_spider.cpp" #include "nonhumans/nonhumanoid_twoheadedmoose.cpp" #include "nonhumans/nonhumanoid_unicorn.cpp" +#include "nonhumans/nonhumanoid_bluedragon.cpp" +#include "nonhumans/nonhumanoid_fruitbat.cpp" +#include "nonhumans/nonhumanoid_okapi.cpp" +#include "nonhumans/nonhumanoid_reddragon.cpp" +#include "nonhumans/nonhumanoid_thunderbird.cpp" #include "nonhumans/nonhumanoid_canine.cpp" #include "nonhumans/canine_wolf.cpp" +#include "nonhumans/canine_firefox.cpp" #include "nonhumans/canine_dog.cpp" #include "nonhumans/dog_blinkdog.cpp" @@ -52,3 +58,6 @@ #include "nonhumans/largecreature_menatrixfusanga.cpp" #include "nonhumans/largecreature_solicitus.cpp" #include "nonhumans/largecreature_vladimir.cpp" +#include "nonhumans/largecreature_anvitas.cpp" +#include "nonhumans/largecreature_genefourxvesana.cpp" +#include "nonhumans/largecreature_haastseagle.cpp" diff --git a/src/game/nonhumans/canine_firefox.cpp b/src/game/nonhumans/canine_firefox.cpp new file mode 100644 index 0000000..fbb9937 --- /dev/null +++ b/src/game/nonhumans/canine_firefox.cpp @@ -0,0 +1,48 @@ +#ifdef HEADER_PHASE +CHARACTER(firefox, canine) +{ +protected: + virtual truth SpecialBiteEffect (character *, v2, int, int, truth); + virtual int GetSpecialBodyPartFlags (int) const; +}; + + +#else + + +int firefox::GetSpecialBodyPartFlags (int) const { return ST_FLAMES; } + + +truth firefox::SpecialBiteEffect (character * Enemy, v2 HitPos, int BodyPartIndex, int Direction, truth BlockedByArmour) { + if (Enemy->IsEnabled() && (RAND()&1)) { + if (Enemy->CanBeSeenByPlayer() && IsPlayer()) { + ADD_MESSAGE("Your bite burns %s.", Enemy->CHAR_DESCRIPTION(DEFINITE)); + } else if (Enemy->IsPlayer() || Enemy->CanBeSeenByPlayer() || CanBeSeenByPlayer()) { + ADD_MESSAGE("The bite of %s burns %s.", CHAR_DESCRIPTION(DEFINITE), Enemy->CHAR_DESCRIPTION(DEFINITE)); + } + Enemy->ReceiveBodyPartDamage(this, 2+(RAND()&3), FIRE, BodyPartIndex, Direction); + Enemy->CheckDeath(CONST_S("killed by the firey bite of ") + GetName(INDEFINITE), this); + return true; + } + return false; +} + + +/* +truth firefox::Bite (character *Enemy, v2 HitPos, int BodyPartIndex, int Direction, truth BlockedByArmour) { + truth BaseSuccess = nonhumanoid::Bite(Enemy, HitPos, BodyPartIndex, Direction, BlockedByArmour); + // + if (Enemy->IsEnabled() && (RAND()&1)) { + if (Enemy->CanBeSeenByPlayer() && IsPlayer()) { + ADD_MESSAGE("Your bite burns %s.", Enemy->CHAR_DESCRIPTION(DEFINITE)); + } else if (Enemy->IsPlayer() || Enemy->CanBeSeenByPlayer() || CanBeSeenByPlayer()) { + ADD_MESSAGE("The bite of %s burns %s.", CHAR_DESCRIPTION(DEFINITE), Enemy->CHAR_DESCRIPTION(DEFINITE)); + } + return Enemy->ReceiveBodyPartDamage(this, 2 + (RAND() & 3), FIRE, BodyPartIndex, Direction) || BaseSuccess; + } + return BaseSuccess; +} +*/ + + +#endif diff --git a/src/game/nonhumans/largecreature_anvitas.cpp b/src/game/nonhumans/largecreature_anvitas.cpp new file mode 100644 index 0000000..112fa37 --- /dev/null +++ b/src/game/nonhumans/largecreature_anvitas.cpp @@ -0,0 +1,22 @@ +#ifdef HEADER_PHASE +CHARACTER(anvitas, largecreature) +{ +public: + virtual void SpecialBodyDefenceEffect (character *, bodypart *, int); +}; + + +#else + + +void anvitas::SpecialBodyDefenceEffect (character *Enemy, bodypart *BodyPart, int Type) { + if (Type != WEAPON_ATTACK && (RAND()&1)) { + if (Enemy->IsPlayer()) ADD_MESSAGE("%s spines jab your %s!", CHAR_POSSESSIVE_PRONOUN, BodyPart->GetBodyPartName().CStr()); + else if (CanBeSeenByPlayer() || Enemy->CanBeSeenByPlayer()) ADD_MESSAGE("%s spines jab %s!", CHAR_POSSESSIVE_PRONOUN, Enemy->CHAR_NAME(DEFINITE)); + Enemy->ReceiveBodyPartDamage(this, 10+(RAND()&6), PHYSICAL_DAMAGE, BodyPart->GetBodyPartIndex(), YOURSELF, false, false, true, false); + Enemy->CheckDeath(CONST_S("killed by the pointy spines of ") + GetName(INDEFINITE), this); + } +} + + +#endif diff --git a/src/game/nonhumans/largecreature_genefourxvesana.cpp b/src/game/nonhumans/largecreature_genefourxvesana.cpp new file mode 100644 index 0000000..0bb0fa6 --- /dev/null +++ b/src/game/nonhumans/largecreature_genefourxvesana.cpp @@ -0,0 +1,143 @@ +#ifdef HEADER_PHASE +CHARACTER(genefourxvesana, largecreature) +{ +public: + genefourxvesana() : TurnsExisted(0), Species(0) {} + + void SetSpecies (int); + int GetSpecies () const { return Species; } + virtual void Save (outputfile &) const; + virtual void Load (inputfile &); + virtual void FinalProcessForBone (); + +protected: + virtual void GetAICommand (); + virtual void CreateCorpse (lsquare *); + virtual truth MustBeRemovedFromBone () const; + +protected: + sLong TurnsExisted; + int Species; +}; + + +#else + + +void genefourxvesana::Save (outputfile &SaveFile) const { + nonhumanoid::Save(SaveFile); + SaveFile << TurnsExisted; + SaveFile << Species; +} + + +void genefourxvesana::Load (inputfile &SaveFile) { + nonhumanoid::Load(SaveFile); + SaveFile >> TurnsExisted; + SaveFile >> Species; +} + + +truth genefourxvesana::MustBeRemovedFromBone () const { + return (!IsEnabled() || GetTeam()->GetID() != MONSTER_TEAM || GetDungeon()->GetIndex() != UNDER_WATER_TUNNEL || GetLevel()->GetIndex() != VESANA_LEVEL); +} + + +void genefourxvesana::FinalProcessForBone () { + largecreature::FinalProcessForBone(); + TurnsExisted = 0; +} + + +void genefourxvesana::CreateCorpse (lsquare* Square) { + for (int c = 0; c < 1; ++c) Square->AddItem(solstone::Spawn()); + largecreature::CreateCorpse(Square); +} + + +void genefourxvesana::GetAICommand () { + StandIdleAI(); + ++TurnsExisted; + SeekLeader(GetLeader()); + if (FollowLeader(GetLeader())) return; + // + if (!(RAND() % 10)) { + int NumberOfPlants = RAND()%3+RAND()%3+RAND()%3+RAND()%3; + // + for (int c1 = 0; c1 < 50 && NumberOfPlants; ++c1) { + for (int c2 = 0; c2 < game::GetTeams() && NumberOfPlants; ++c2) { + if (GetTeam()->GetRelation(game::GetTeam(c2)) == HOSTILE) { + for (std::list::const_iterator i = game::GetTeam(c2)->GetMember().begin(); i != game::GetTeam(c2)->GetMember().end() && NumberOfPlants; ++i) { + if ((*i)->IsEnabled()) { + lsquare *LSquare = (*i)->GetNeighbourLSquare(RAND()%GetNeighbourSquares()); + // + if (LSquare && (LSquare->GetWalkability() & WALK) && !LSquare->GetCharacter()) { + character *NewPlant; + sLong RandomValue = RAND()%TurnsExisted; + // + if (RandomValue < 250) NewPlant = carnivorousplant::Spawn(GIANT); + else if (RandomValue < 1500) NewPlant = carnivorousplant::Spawn(LILY); + else NewPlant = carnivorousplant::Spawn(SHAMBLING); + // + for (int c = 3; c < TurnsExisted / 500; ++c) NewPlant->EditAllAttributes(1); + // + NewPlant->SetGenerationDanger(GetGenerationDanger()); + NewPlant->SetTeam(GetTeam()); + NewPlant->PutTo(LSquare->GetPos()); + --NumberOfPlants; + // + if (NewPlant->CanBeSeenByPlayer()) { + if ((*i)->IsPlayer()) ADD_MESSAGE("%s sprouts from the ground near you.", NewPlant->CHAR_NAME(INDEFINITE)); + else if ((*i)->CanBeSeenByPlayer()) ADD_MESSAGE("%s sprouts from the ground near %s.", NewPlant->CHAR_NAME(INDEFINITE), (*i)->CHAR_NAME(DEFINITE)); + else ADD_MESSAGE("%s sprouts from the ground.", NewPlant->CHAR_NAME(INDEFINITE)); + } + } + } + } + } + } + // + SeekLeader(GetLeader()); + if (FollowLeader(GetLeader())) return; + // + lsquare *CradleSquare = GetNeighbourLSquare(RAND()%8); + // + if (CradleSquare && !CradleSquare->GetCharacter() && (CradleSquare->GetWalkability() & WALK)) { + int SpoiledItems = 0; + int MushroomsNear = 0; + // + for (int d = 0; d < 8; ++d) { + lsquare *Square = CradleSquare->GetNeighbourLSquare(d); + // + if (Square) { + character *Char = Square->GetCharacter(); + // + if (Char && Char->IsMushroom()) ++MushroomsNear; + SpoiledItems += Square->GetSpoiledItems(); + } + } + // + if ((SpoiledItems && MushroomsNear < 1 && !RAND_N(2)) || (MushroomsNear < 3 && !RAND_N((1+MushroomsNear)*2))) { + carnivorousplant *Child = carnivorousplant::Spawn(SHAMBLING); + // + Child->SetTeam(GetTeam()); + Child->SetGenerationDanger(GetGenerationDanger()); + Child->PutTo(CradleSquare->GetPos()); + if (Child->CanBeSeenByPlayer()) ADD_MESSAGE("%s sprouts from the ground.", Child->CHAR_NAME(INDEFINITE)); + } + } + // + if (AttackAdjacentEnemyAI()) return; + if (MoveRandomly()) return; + EditAP(-1000); + } + EditAP(-2000); + return; + } + if (AttackAdjacentEnemyAI()) return; + if (MoveRandomly()) return; + EditAP(-1000); +} + + +#endif diff --git a/src/game/nonhumans/largecreature_haastseagle.cpp b/src/game/nonhumans/largecreature_haastseagle.cpp new file mode 100644 index 0000000..ba2b157 --- /dev/null +++ b/src/game/nonhumans/largecreature_haastseagle.cpp @@ -0,0 +1,21 @@ +#ifdef HEADER_PHASE +CHARACTER(haastseagle, largecreature) +{ +protected: + virtual cchar *FirstPersonBiteVerb () const; + virtual cchar *FirstPersonCriticalBiteVerb () const; + virtual cchar *ThirdPersonBiteVerb () const; + virtual cchar *ThirdPersonCriticalBiteVerb () const; +}; + + +#else + + +cchar *haastseagle::FirstPersonBiteVerb() const { return "peck"; } +cchar *haastseagle::FirstPersonCriticalBiteVerb() const { return "critically peck"; } +cchar *haastseagle::ThirdPersonBiteVerb() const { return "pecks"; } +cchar *haastseagle::ThirdPersonCriticalBiteVerb() const { return "critically pecks"; } + + +#endif diff --git a/src/game/nonhumans/nonhumanoid_bluedragon.cpp b/src/game/nonhumans/nonhumanoid_bluedragon.cpp new file mode 100644 index 0000000..458b27a --- /dev/null +++ b/src/game/nonhumans/nonhumanoid_bluedragon.cpp @@ -0,0 +1,5 @@ +#ifdef HEADER_PHASE +CHARACTER(bluedragon, nonhumanoid) +{ +}; +#endif diff --git a/src/game/nonhumans/nonhumanoid_fruitbat.cpp b/src/game/nonhumans/nonhumanoid_fruitbat.cpp new file mode 100644 index 0000000..c41d592 --- /dev/null +++ b/src/game/nonhumans/nonhumanoid_fruitbat.cpp @@ -0,0 +1,52 @@ +#ifdef HEADER_PHASE +CHARACTER(fruitbat, nonhumanoid) +{ +public: + virtual void GetAICommand (); + virtual truth IsRetreating () const; + +protected: + virtual bodypart *MakeBodyPart (int) const; +}; + + +#else + + +bodypart *fruitbat::MakeBodyPart (int) const { return battorso::Spawn(0, NO_MATERIALS); } + + +truth fruitbat::IsRetreating () const { + if (nonhumanoid::IsRetreating()) return true; + for (stackiterator i = GetStack()->GetBottom(); i.HasItem(); ++i) { + if ((*i)/*->GetMainMaterial()->IsFruit()*/->IsFood()) return true; + } + return false; +} + + +void fruitbat::GetAICommand () { + if (!IsRetreating()) { + character *Char = GetRandomNeighbour(); + // + if (Char) { + itemvector Fruits; + // + for (stackiterator i = Char->GetStack()->GetBottom(); i.HasItem(); ++i) { + if (((*i)->IsFood()/*->GetMainMaterial()->IsFruit())*/) && !MakesBurdened((*i)->GetWeight())) Fruits.push_back(*i); + } + if (!Fruits.empty()) { + item *ToSteal = Fruits[RAND()%Fruits.size()]; + ToSteal->RemoveFromSlot(); + GetStack()->AddItem(ToSteal); + if (Char->IsPlayer()) ADD_MESSAGE("%s steals your %s.", CHAR_NAME(DEFINITE), ToSteal->CHAR_NAME(UNARTICLED)); + EditAP(-500); + return; + } + } + } + nonhumanoid::GetAICommand(); +} + + +#endif diff --git a/src/game/items/item_mango.cpp b/src/game/nonhumans/nonhumanoid_okapi.cpp similarity index 51% copy from src/game/items/item_mango.cpp copy to src/game/nonhumans/nonhumanoid_okapi.cpp index 4f7a9ae..753565e 100644 --- a/src/game/items/item_mango.cpp +++ b/src/game/nonhumans/nonhumanoid_okapi.cpp @@ -1,5 +1,5 @@ #ifdef HEADER_PHASE -ITEM(mango, item) +CHARACTER(okapi, nonhumanoid) { }; #endif diff --git a/src/game/nonhumans/nonhumanoid_reddragon.cpp b/src/game/nonhumans/nonhumanoid_reddragon.cpp new file mode 100644 index 0000000..595154b --- /dev/null +++ b/src/game/nonhumans/nonhumanoid_reddragon.cpp @@ -0,0 +1,5 @@ +#ifdef HEADER_PHASE +CHARACTER(reddragon, nonhumanoid) +{ +}; +#endif diff --git a/src/game/nonhumans/nonhumanoid_thunderbird.cpp b/src/game/nonhumans/nonhumanoid_thunderbird.cpp new file mode 100644 index 0000000..358b8fb --- /dev/null +++ b/src/game/nonhumans/nonhumanoid_thunderbird.cpp @@ -0,0 +1,39 @@ +#ifdef HEADER_PHASE +CHARACTER(thunderbird, nonhumanoid) +{ +protected: + virtual cchar *FirstPersonBiteVerb () const; + virtual cchar *FirstPersonCriticalBiteVerb () const; + virtual cchar *ThirdPersonBiteVerb () const; + virtual cchar *ThirdPersonCriticalBiteVerb () const; + virtual int GetSpecialBodyPartFlags (int) const; + virtual truth SpecialBiteEffect (character *, v2, int, int, truth); +}; + + +#else + + +cchar *thunderbird::FirstPersonBiteVerb () const { return "peck"; } +cchar *thunderbird::FirstPersonCriticalBiteVerb () const { return "critically peck"; } +cchar *thunderbird::ThirdPersonBiteVerb () const { return "pecks"; } +cchar *thunderbird::ThirdPersonCriticalBiteVerb () const { return "critically pecks"; } +int thunderbird::GetSpecialBodyPartFlags (int) const { return ST_LIGHTNING; } + + +truth thunderbird::SpecialBiteEffect (character *Enemy, v2 HitPos, int BodyPartIndex, int Direction, truth BlockedByArmour) { + if (Enemy->IsEnabled() && (RAND()&1)) { + if (Enemy->CanBeSeenByPlayer() && IsPlayer()) { + ADD_MESSAGE("Your beak emits a thunderous peal directed at %s.", Enemy->CHAR_DESCRIPTION(DEFINITE)); + } else if (Enemy->IsPlayer() || Enemy->CanBeSeenByPlayer() || CanBeSeenByPlayer()) { + ADD_MESSAGE("Thunder is emitted from the beak of %s and the sound waves hit %s.", CHAR_DESCRIPTION(DEFINITE), Enemy->CHAR_DESCRIPTION(DEFINITE)); + } + Enemy->ReceiveBodyPartDamage(this, 2+(RAND()&3), SOUND, BodyPartIndex, Direction); + Enemy->CheckDeath(CONST_S("killed by the thunderous attack of ") + GetName(INDEFINITE), this); + return true; + } + return false; +} + + +#endif diff --git a/src/game/worldmap.cpp b/src/game/worldmap.cpp index 0ab9483..8fcef36 100644 --- a/src/game/worldmap.cpp +++ b/src/game/worldmap.cpp @@ -115,17 +115,24 @@ void worldmap::Generate () { PerfectForAttnam.push_back(Continent[c]); } if (!PerfectForAttnam.size()) continue; - + // v2 AttnamPos, ElpuriCavePos, NewAttnamPos, TunnelEntry, TunnelExit, MondedrPos, MuntuoPos; + v2 DragonTowerPos, DarkForestPos, XinrochTombPos; truth Correct = false; continent *PetrusLikes; + // for (int c1 = 0; c1 < 25; ++c1) { game::BusyAnimation(); + // PetrusLikes = PerfectForAttnam[RAND() % PerfectForAttnam.size()]; AttnamPos = PetrusLikes->GetRandomMember(EGForestType); ElpuriCavePos = PetrusLikes->GetRandomMember(SnowType); MondedrPos = PetrusLikes->GetRandomMember(SteppeType); MuntuoPos = PetrusLikes->GetRandomMember(LForestType); + DragonTowerPos = PetrusLikes->GetRandomMember(SteppeType); + DarkForestPos = PetrusLikes->GetRandomMember(LForestType); + XinrochTombPos = PetrusLikes->GetRandomMember(SnowType); + // for (int c2 = 1; c2 < 50; ++c2) { TunnelExit = PetrusLikes->GetMember(RAND() % PetrusLikes->GetSize()); if (AttnamPos != TunnelExit && ElpuriCavePos != TunnelExit) { @@ -203,20 +210,37 @@ void worldmap::Generate () { if (Correct) break; } if (!Correct) continue; + // GetWSquare(AttnamPos)->ChangeOWTerrain(attnam::Spawn()); SetEntryPos(ATTNAM, AttnamPos); RevealEnvironment(AttnamPos, 1); + // GetWSquare(NewAttnamPos)->ChangeOWTerrain(newattnam::Spawn()); SetEntryPos(NEW_ATTNAM, NewAttnamPos); + // SetEntryPos(ELPURI_CAVE, ElpuriCavePos); + // SetEntryPos(MONDEDR, MondedrPos); + // GetWSquare(TunnelEntry)->ChangeOWTerrain(underwatertunnel::Spawn()); SetEntryPos(UNDER_WATER_TUNNEL, TunnelEntry); + // GetWSquare(TunnelExit)->ChangeOWTerrain(underwatertunnelexit::Spawn()); SetEntryPos(UNDER_WATER_TUNNEL_EXIT, TunnelExit); + // GetWSquare(MuntuoPos)->ChangeOWTerrain(muntuo::Spawn()); SetEntryPos(MUNTUO, MuntuoPos); + // + GetWSquare(DragonTowerPos)->ChangeOWTerrain(dragontower::Spawn()); + SetEntryPos(DRAGON_TOWER, DragonTowerPos); + // + GetWSquare(DarkForestPos)->ChangeOWTerrain(darkforest::Spawn()); + SetEntryPos(DARK_FOREST, DarkForestPos); + // + SetEntryPos(XINROCH_TOMB, XinrochTombPos); + // PLAYER->PutTo(NewAttnamPos); + // CalculateLuminances(); CalculateNeighbourBitmapPoses(); break; diff --git a/src/game/wterrains/owterrains/0list.cpp b/src/game/wterrains/owterrains/0list.cpp index 7b82769..4052fcf 100644 --- a/src/game/wterrains/owterrains/0list.cpp +++ b/src/game/wterrains/owterrains/0list.cpp @@ -5,3 +5,6 @@ #include "wterrains/owterrains/owterrain_elpuricave.cpp" #include "wterrains/owterrains/owterrain_mondedr.cpp" #include "wterrains/owterrains/owterrain_muntuo.cpp" +#include "wterrains/owterrains/owterrain_darkforest.cpp" +#include "wterrains/owterrains/owterrain_dragontower.cpp" +#include "wterrains/owterrains/owterrain_xinrochtomb.cpp" diff --git a/src/game/wterrains/owterrains/owterrain_darkforest.cpp b/src/game/wterrains/owterrains/owterrain_darkforest.cpp new file mode 100644 index 0000000..c175c67 --- /dev/null +++ b/src/game/wterrains/owterrains/owterrain_darkforest.cpp @@ -0,0 +1,19 @@ +#ifdef HEADER_PHASE +OWTERRAIN(darkforest, owterrain) +{ +public: + virtual const char *GetNameStem () const; + virtual v2 GetBitmapPos (int) const; + virtual int GetAttachedDungeon () const; +}; + + +#else + + +cchar *darkforest::GetNameStem () const { return "dark forest"; } +v2 darkforest::GetBitmapPos (int) const { return v2(80, 80); } +int darkforest::GetAttachedDungeon () const { return DARK_FOREST; } + + +#endif diff --git a/src/game/wterrains/owterrains/owterrain_dragontower.cpp b/src/game/wterrains/owterrains/owterrain_dragontower.cpp new file mode 100644 index 0000000..e15f221 --- /dev/null +++ b/src/game/wterrains/owterrains/owterrain_dragontower.cpp @@ -0,0 +1,19 @@ +#ifdef HEADER_PHASE +OWTERRAIN(dragontower, owterrain) +{ +public: + virtual cchar *GetNameStem () const; + virtual v2 GetBitmapPos (int) const; + virtual int GetAttachedDungeon () const; +}; + + +#else + + +cchar *dragontower::GetNameStem () const { return "ruined tower"; } +v2 dragontower::GetBitmapPos (int) const { return v2(50, 80); } +int dragontower::GetAttachedDungeon () const { return DRAGON_TOWER; } + + +#endif diff --git a/src/game/wterrains/owterrains/owterrain_xinrochtomb.cpp b/src/game/wterrains/owterrains/owterrain_xinrochtomb.cpp new file mode 100644 index 0000000..9c8fd22 --- /dev/null +++ b/src/game/wterrains/owterrains/owterrain_xinrochtomb.cpp @@ -0,0 +1,19 @@ +#ifdef HEADER_PHASE +OWTERRAIN(xinrochtomb, owterrain) +{ +public: + virtual cchar *GetNameStem () const; + virtual v2 GetBitmapPos (int) const; + virtual int GetAttachedDungeon () const; +}; + + +#else + + +cchar *xinrochtomb::GetNameStem () const { return "tomb of utter darkness where dwells the soul of Xinroch"; } +v2 xinrochtomb::GetBitmapPos (int) const { return v2(64, 80); } +int xinrochtomb::GetAttachedDungeon () const { return XINROCH_TOMB; } + + +#endif -- 2.11.4.GIT