Modding:Tutorial/The Infinite Arena/Source

From DoomRL Wiki

Revision as of 21:12, 1 October 2011 by Game Hunter (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search
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 a considered 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
 
--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
				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()
	arena.result = "had enough of the gauntlet at wave "..Level.result()
end
 
function arena.OnMortem()
    local kill = player.killedby --calls kill descriptions from beings
    if arena.result then kill = 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
Personal tools