Modding:Tutorial/The Infinite Arena/Source
From DoomRL Wiki
Revision as of 02:06, 8 October 2011 by Game Hunter (Talk | contribs)
core.declare("inf_arena", {} ) --enemy scaling for each wave: note that game difficulty will modify scaling independently local mob_scale_factor = 0.5 --customize minLev/maxLev/weight of each enemy (defaults given) --for names of beings, check Object IDs in the modding documentation --be aware that JC auto-ends the game unless modified directly local mobGenStats = { { being = "former", minLev = 0, maxLev = 12, weight = 10 }, { being = "sergeant", minLev = 2, maxLev = 15, weight = 10 }, { being = "captain", minLev = 8, maxLev = 15, weight = 10 }, { being = "imp", minLev = 0, maxLev = 17, weight = 8 }, { being = "demon", minLev = 4, maxLev = 20, weight = 6 }, { being = "lostsoul", minLev = 6, maxLev = 16, weight = 10 }, { being = "knight", minLev = 9, maxLev = 15, weight = 6 }, { being = "cacodemon", minLev = 10, maxLev = 50, weight = 6 }, { being = "commando", minLev = 12, maxLev = 17, weight = 6 }, { being = "pain", minLev = 12, maxLev = 17, weight = 2 }, { being = "baron", minLev = 12, maxLev = 200, weight = 6 }, { being = "arachno", minLev = 13, maxLev = 50, weight = 4 }, { being = "revenant", minLev = 13, maxLev = 200, weight = 5 }, { being = "mancubus", minLev = 15, maxLev = 200, weight = 7 }, { being = "arch", minLev = 16, maxLev = 200, weight = 4 }, { being = "nimp", minLev = 30, maxLev = 60, weight = 8 }, { being = "ndemon", minLev = 40, maxLev = 200, weight = 6 }, { being = "ncacodemon", minLev = 51, maxLev = 200, weight = 6 }, { being = "narachno", minLev = 50, maxLev = 200, weight = 5 }, { being = "narch", minLev = 90, maxLev = 200, weight = 3 }, { being = "bruiser", minLev = 50, maxLev = 200, weight = 6 }, { being = "lava_elemental", minLev = 70, maxLev = 200, weight = 1 }, { being = "shambler", minLev = 80, maxLev = 200, weight = 3 }, { being = "agony", minLev = 80, maxLev = 200, weight = 1 }, { being = "cyberdemon", minLev = 80, maxLev = 200, weight = 1 }, { being = "arenamaster", minLev = 0, maxLev = 0, weight = 0 }, { being = "angel", minLev = 0, maxLev = 0, weight = 0 }, { being = "jc", minLev = 0, maxLev = 0, weight = 0 }, } --item scaling for each wave local item_scale_factor = 0.5 --customize level/weight of items (defaults given) --for names of items, check Object IDs in the modding documentation local itemGenStats = { --Commons --weapons { item = "knife", level = 1, weight = 640 }, { item = "pistol", level = 1, weight = 70 }, { item = "shotgun", level = 2, weight = 180 }, { item = "ashotgun", level = 2, weight = 160 }, { item = "dshotgun", level = 4, weight = 100 }, { item = "chaingun", level = 5, weight = 200 }, { item = "bazooka", level = 7, weight = 200 }, { item = "plasma", level = 12, weight = 70 }, --ammo/ammo packs { item = "ammo", level = 1, weight = 500 }, { item = "pammo", level = 3, weight = 700 }, { item = "shell", level = 2, weight = 400 }, { item = "pshell", level = 4, weight = 200 }, { item = "rocket", level = 5, weight = 60 }, { item = "procket", level = 7, weight = 60 }, { item = "cell", level = 8, weight = 36 }, { item = "pcell", level = 10, weight = 18 }, --armor/boots { item = "garmor", level = 1, weight = 400 }, { item = "barmor", level = 4, weight = 240 }, { item = "rarmor", level = 7, weight = 150 }, { item = "sboots", level = 4, weight = 240 }, { item = "pboots", level = 7, weight = 150 }, { item = "psboots", level = 11, weight = 80 }, --consumables { item = "smed", level = 1, weight = 600 }, { item = "lmed", level = 5, weight = 400 }, { item = "phase", level = 5, weight = 200 }, { item = "hphase", level = 7, weight = 100 }, { item = "epack", level = 5, weight = 100 }, { item = "nuke", level = 10, weight = 40 }, { item = "lava_element", level = 23, weight = 0 }, { item = "mod_power", level = 7, weight = 120 }, { item = "mod_tech", level = 6, weight = 120 }, { item = "mod_bulk", level = 6, weight = 120 }, { item = "mod_agility", level = 5, weight = 120 }, --powerups { item = "shglobe", level = 1, weight = 900 }, { item = "lhglobe", level = 6, weight = 330 }, { item = "scglobe", level = 4, weight = 150 }, { item = "bpack", level = 1, weight = 200 }, { item = "iglobe", level = 7, weight = 200 }, { item = "msglobe", level = 16, weight = 60 }, { item = "map", level = 1, weight = 200 }, { item = "pmap", level = 1, weight = 80 }, { item = "ashard", level = 5, weight = 700 }, { item = "backpack", level = 7, weight = 0 }, --Exotics --weapons { item = "chainsaw", level = 12, weight = 3 }, { item = "ublaster", level = 4, weight = 2 }, { item = "uashotgun", level = 6, weight = 6 }, { item = "upshotgun", level = 12, weight = 4 }, { item = "udshotgun", level = 10, weight = 5 }, { item = "uminigun", level = 10, weight = 6 }, { item = "umbazooka", level = 10, weight = 6 }, { item = "unapalm", level = 10, weight = 6 }, { item = "ulaser", level = 12, weight = 5 }, { item = "unplasma", level = 15, weight = 4 }, { item = "utristar", level = 12, weight = 4 }, { item = "bfg9000", level = 20, weight = 2 }, { item = "unbfg9000", level = 22, weight = 2 }, { item = "utrans", level = 14, weight = 3 }, --armor/boots { item = "uoarmor", level = 7, weight = 4 }, { item = "uparmor", level = 10, weight = 6 }, { item = "upboots", level = 8, weight = 6 }, { item = "ugarmor", level = 15, weight = 6 }, { item = "ugboots", level = 10, weight = 6 }, { item = "umedarmor", level = 5, weight = 6 }, { item = "uduelarmor", level = 5, weight = 6 }, { item = "ubulletarmor", level = 2, weight = 4 }, { item = "uballisticarmor", level = 2, weight = 5 }, { item = "ueshieldarmor", level = 5, weight = 3 }, { item = "uplasmashield", level = 10, weight = 3 }, { item = "uenergyshield", level = 8, weight = 3 }, { item = "ubalshield", level = 6, weight = 3 }, { item = "uacidboots", level = 8, weight = 5 }, --consumables { item = "uswpack", level = 5, weight = 10 }, { item = "ubskull", level = 5, weight = 8 }, { item = "ufskull", level = 7, weight = 8 }, { item = "uhskull", level = 9, weight = 8 }, { item = "umod_firestorm", level = 10, weight = 4 }, { item = "umod_sniper", level = 10, weight = 2 }, --Uniques --weapons { item = "ubutcher", level = 1, weight = 2 }, { item = "spear", level = 16, weight = 0 }, { item = "uscythe", level = 16, weight = 0 }, { item = "utrigun", level = 8, weight = 2 }, { item = "ujackal", level = 10, weight = 2 }, { item = "uberetta", level = 6, weight = 3 }, { item = "usjack", level = 12, weight = 2 }, { item = "urbazooka", level = 12, weight = 2 }, { item = "uacid", level = 12, weight = 3 }, { item = "urailgun", level = 15, weight = 2 }, { item = "ubfg10k", level = 20, weight = 1 }, --armor/boots { item = "umarmor", level = 15, weight = 3 }, { item = "ucarmor", level = 10, weight = 2 }, { item = "unarmor", level = 10, weight = 3 }, { item = "umedparmor", level = 10, weight = 2 }, { item = "ulavaarmor", level = 12, weight = 2 }, { item = "uenviroboots", level = 10, weight = 2 }, { item = "ushieldarmor", level = 10, weight = 2 }, { item = "aarmor", level = 22, weight = 0 }, --consumables { item = "uhwpack", level = 10, weight = 4 }, { item = "umodstaff", level = 15, weight = 4 }, { item = "uarenastaff", level = 4, weight = 0 }, { item = "umod_nano", level = 10, weight = 1 }, { item = "umod_onyx", level = 10, weight = 1 }, } --changes the generation stats of enemies based on mobGenStats for _,v in ipairs(mobGenStats) do beings[v.being].minLev = v.minLev beings[v.being].maxLev = v.maxLev beings[v.being].weight = v.weight end --changes the generation stats of items based on itemGenStats for _,v in ipairs(itemGenStats) do items[v.item].level = v.level items[v.item].weight = v.weight end --add your own announcer lines here local anncrMsg = { --displays whenever player completes wave success = { { "The voice booms, \"Congratulations mortal!", "The voice booms, \"Impressive mortal!", "The voice booms, \"Most impressive.", "The voice booms, \"You are a formidable warrior!", }, { "Each of your triumphs is a work of art!", "Your ability to survive is incredible!", "You've given us a great show!", "You would make a terrific hell warrior!", }, { "But can you keep going?\"", "How much longer can you go?\"", "Will you fight with us a little more?\"", "I can let you go now if you like, or...\"", } }, --displays whenever player decides to continue to another wave choice = { { "The voice booms, \"I like it! Let the show go on!\"", "The voice booms, \"Excellent! May the fight begin!!!\"", }, { "You hear screams everywhere! \"More Blood! More BLOOD!\"", "You hear screams everywhere! \"Kill, Kill, KILL!\"", } } } --add your own crowd lines here --displays whenever enemy is killed local crowdMsg = { "The crowd goes wild! \"BLOOD! BLOOD!\"", "The crowd cheers! \"Blood! Blood!\"", "The crowd cheers! \"Kill! Kill!\"", "The crowd hisses. \"We came for a REAL fight!\"", "The crowd boos. \"No skill, no kill!\"", } local function build_announcerMsg(MSG) for _,msgNum in ipairs(MSG) do ui.msg(table.random_pick(msgNum)) end end --from Skulltag Arena, credit goes to yaflhdztioxo --initializes table of cells that contains only corpses local corpseCells = {} local function get_corpses() for i = 1, #cells do if cells[i] and cells[i].flags then if cells[i].flag_set[CF_CORPSE] == true then table.insert(corpseCells, i) --i == sID's numeric value end end end end --removes corpses and blood-like cells local function clear_corpses() --fade away all blood Generator.transmute("blood", "floor") Generator.transmute("bloodpool", "blood") --changes corpses to blood for i = 1, #corpseCells do Generator.transmute(corpseCells[i], "bloodpool") end end --changes player equipment --add "nil" for any slot that should be empty --always refreshes all slots: do not use to change only one equipment slot local function build_gear(weap,prep,body,foot) player.eq:clear() if weap then player.eq.weapon = item.new(weap) end --main weapon if prep then player.eq.prepared = item.new(prep) end --prepared weapon if body then player.eq.armor = item.new(body) end --body armor if foot then player.eq.boots = item.new(foot) end --boots end --changes player inventory --always refreshes all slots: do not use to change only one equipment slot --[[ input is an array of tables with two fields: -name is the identifier of the item that goes in the inventory -amt is how many items should be added (or how many units of ammo) example table (based on default inventory): local starter_pack = { {name = "ammo", amt = 24}, {name = "smed", amt = 2}, } --]] local function build_pack(itemPack) player.inv:clear() for _,part in ipairs(itemPack) do if items[part.name].type == ITEMTYPE_AMMO then --ammo is handled separately, loops for however many stacks are needed for n=1,math.ceil(part.amt/items[part.name].ammomax) do local pack = item.new(part.name) if part.amt < pack.ammomax then --remainder (or single) stack pack.ammo = part.amt else --filled (and/or multiple) stacks pack.ammo = pack.ammomax part.amt = part.amt - pack.ammomax end player.inv:add(pack) end else --loops for however many items are needed for n=1,part.amt do player.inv:add(part.name) end end end end function inf_arena.OnEnter() --inventory table used for build_pack() local itemPack = { {name = "smed", amt = 2}, {name = "shell", amt = 50}, } --set up starting eq/inv build_gear("shotgun","pistol",nil,nil) build_pack(itemPack) --Print announcer messages ui.msg("A devilish voice announces: \"Welcome to Hell's Arena, mortal! " .. "\"You are either very brave or very foolish. Either way I like it! " .. "\"And so do the crowds!\" Suddenly you hear screams everywhere! " .. "\"Blood! Blood! BLOOD!\" \"Kill all enemies and I shall reward thee!\"") --spawn first wave Level.flood_monsters(Generator.being_weight()*mob_scale_factor) Level.result(1) end function inf_arena.OnKill(being) --random message from crowdMsg array ui.msg(table.random_pick(crowdMsg)) end function inf_arena.OnKillAll() --print more announcer stuff if Level.result() == 1 then ui.msg("The voice booms, \"Not bad mortal! For a weakling that you are, " .. "you show some determination.\" You hear screams everywhere! " .. "\"More Blood! More BLOOD!\" The voice continues, \"I can now " .. "let you go free, or you may try to complete the challenge!\"") elseif Level.result() == 2 then ui.msg("The voice booms, \"Impressive mortal! Your determination to " .. "survive makes me excited!\" You hear screams everywhere! " .. "\"More Blood! More BLOOD!\" \"I can let you go now, and give you " .. "a small reward, or you can choose to fight an additional challenge!\"") else --random message from anncrMsg.success array build_announcerMsg(anncrMsg.success) end local choice = ui.msg_confirm("Round " .. Level.result() + 1 .. " awaits. " .. "Do you want to continue the fight?") if choice == true then --continuing --random message from anncrMsg.choice array build_announcerMsg(anncrMsg.choice) --set up the danger level for the next wave Level.result(Level.result() + 1); Level.danger_level = Level.result(); --spawn items for next wave Level.flood_items(Generator.item_amount()*item_scale_factor) --spawn enemies for next wave Level.flood_monsters(Generator.being_weight()*mob_scale_factor) else --quitting if Level.result() == 1 then ui.msg("The voice booms, \"Coward!\" You hear screams everywhere! " .. "\"Coward! Coward! COWARD!\"") elseif Level.result() == 2 then ui.msg("The voice booms, \"Too bad, you won't make it far then...!\" " .. "You hear screams everywhere! \"Boooo...\"") elseif Level.result() < 10 then ui.msg("The voice booms, \"An impressive run, Mortal! We appreciate " .. "it!\" The crowd starts to chant! \"Encore! Encore!\"") else ui.msg("\"Ladies and gentlemen, your champion, " .. Player.get_name() .. ". He survived " .. Level.result() .. " rounds in our arena! That has to be some sort of record. " .. "Give him a hand folks!\" The crowd starts to chant your name " .. "and they begin throwing items into the ring!") Level.flood_items(Generator.item_weight()) end end end function inf_arena.OnExit() if Level.result() < 10 then ui.msg("The voice laughs, \"Flee mortal, flee! There's no hiding in hell!\"") else ui.msg("The voice laughs, \"Remember to come back once you return to Hell " .. "for the extended stay\"") end --used in .OnMortem() inf_arena.result = "had enough of the gauntlet at wave "..Level.result() end function inf_arena.OnMortem() local kill = player.killedby --calls kill descriptions from beings if inf_arena.result then kill = inf_arena.result end player:mortem_print( " "..player.name..", level "..player.explevel.." " .." "..klasses[player.klass].name..", "..kill ) --e.g., "Cool Guy, level 1 Marine, had enough of the gauntlet at wave 8" player:mortem_print(" in the Infinite Arena...") end --Creation of Infinite Arena function inf_arena.run() Level.name = "Infinite Arena" Level.name_number = 0 Level.fill("prwall") local translation = { ["."] = "floor", ["#"] = "prwall", ["X"] = "pwall", [","] = "blood", [">"] = "stairs", } local map = [[ #######################.............................######################## ###########.....................................................############ #####..................................................................##### ##........................................................................## #..........................................................................# ....,....................................................................... .................................,...,...................................... .,.....................................,.................................... ..,>.,..........................,........................................... .,..,.................................,.,................................... ................................,..,...,.................................... ............................................................................ ............................................................................ #..........................................................................# ##........................................................................## #####..................................................................##### ###########.....................................................############ #######################.............................######################## ]] --change up the column types local column = { [[ ,..,., ,XXXX. .X##X, .XXXX. ,..,., ]], [[ ,..,., ,X##X. .####, .X##X. ,..,., ]], [[ ,..,., ,####. .####, .####. ,..,., ]] } Level.place_tile(translation,map,2,2) for i=1,11 + math.random(4) do Level.scatter_put( area.new(5,3,68,15), translation, table.random_pick(column), "floor", 1) end Level.scatter(area.FULL_SHRINKED, "floor", "blood", 100) Level.player(38, 10) end