--entries in registered look like this: --registered[playerInfo] = {portal number, player info, {level items}, "current class", "next class"}; registered = {}; portals = {}; bombs = {}; function clearItems(items) if (items ~= nil) then for k,v in pairs(items) do if (v ~= nil) then if (portals[v:getId()] == true) then portals[v:getId()] = nil; end v:removeFromGame(); end end end end function lineOfSight(ship, backup, maxDist) maxDist = maxDist*maxDist; local speed = 5; local dir = ship:getAngle(); local p1 = ship:getPos(); local p2 = p1; local movementV = point.new(speed*math.cos(dir), speed*math.sin(dir)); while (bf:pointCanSeePoint(p1, p2)) do if (point.distSquared(p1,p2+movementV) > maxDist) then return {p1,p2}; end p2 = p2 + movementV; end --turn around 180 degrees, move away dir = dir + math.pi; speed = backup; movementV = point.new(speed*math.cos(dir), speed*math.sin(dir)); p2 = p2 + movementV; return {p1,p2}; end function itemLine(ship, itemType, dist) local dir = ship:getAngle(); local p1 = ship:getPos(); local p2 = p1; local movementV = point.new(dist*math.cos(dir), dist*math.sin(dir)); while (bf:pointCanSeePoint(p1, p2)) do p2 = p2 + movementV; local item = itemType.new(); item:setTeam(ship:getTeamIndex()); item:setPos(p2); bf:addItem(item); end end function itemCircle(ship, itemType, r, number) local loc = ship:getPos(); for i=1,number,1 do local dist = math.pi*i*(2/number); local item = itemType.new(); item:setPos(loc+point.new(r*math.cos(dist),r*math.sin(dist))); item:setTeam(ship:getTeamIndex()); bf:addItem(item); item:setOwner(ship:getPlayerInfo():getName()); end end function placeFree(p, r) for i=1,12,1 do local pNew = p + point.new(r*math.cos(i*math.pi/6),r*math.sin(i*math.pi/6)); if (bf:pointCanSeePoint(p, pNew) == false) then return false; end end return true; end --classes --cloak function cloakSave(ship) local player = ship:getPlayerInfo(); if (ship:isModActive(Module.Cloak)) then registered[player][1] = 2; --We want the rate energy is lost to go up with the speed of the ship --450 is max speed --.002 is normal energy loss rate local speed = point.length(ship:getVel()); local recovery = .002-((speed/450)*.002); ship:setEnergy(ship:getEnergy() + recovery); else if (registered[player][1] == 2) then ship:setEnergy(ship:getEnergy()-.5); itemCircle(ship, Mine, 0, 1); end registered[player][1] = 1; end end --end cloak --flame function throwFire(ship) if (ship:isModActive(Module.Shield))then local item = Projectile.new(); local angle = ship:getAngle(); local loc = ship:getPos(); local dist = (.2*255); local flspeed = (.5*255); local angle_variance = (math.random()*(math.pi/3))-(math.pi/6); item:setPos(loc+point.new(dist*math.cos(angle),dist*math.sin(angle))); item:setVel(point.new(flspeed*math.cos(angle+angle_variance),flspeed*math.sin(angle+angle_variance))); bf:addItem(item); item:setTeam(ship:getTeamIndex()); item:setOwner(ship:getPlayerInfo():getName()); item = Projectile.new(); angle_variance = (math.random()*(math.pi/3))-(math.pi/6); item:setPos(loc+point.new(dist*math.cos(angle),dist*math.sin(angle))); item:setVel(point.new(flspeed*math.cos(angle+angle_variance),flspeed*math.sin(angle+angle_variance))); bf:addItem(item); item:setTeam(ship:getTeamIndex()); item:setOwner(ship:getPlayerInfo():getName()); ship:setEnergy(ship:getEnergy()-.005); end end --end flame --medic function superHeal(ship) if (ship:isModActive(Module.Cloak))then if (ship:getEnergy() > .7) then local item = RepairItem.new(); local angle = ship:getAngle(); local loc = ship:getPos(); local dist = (.2*255); item:setPos(loc+point.new(dist*math.cos(angle),dist*math.sin(angle))); item:setRegenTime(30*60); bf:addItem(item); ship:setEnergy(ship:getEnergy()-.7); end end end --end medic --shotgunner function kamikaze(ship) if (ship:isModActive(Module.Cloak)) then local name = ship:getPlayerInfo():getName(); bombs[name] = {}; bombs[name][1] = ship:getPos(); bombs[name][2] = 1; --detonate in 1/1000 seconds bombs[name][3] = 2; --do 2 rounds of explosions bombs[name][4] = ship; --itemCircle(ship, Burst, 30, 10); --itemCircle(ship, Projectile, 45, 5); --itemCircle(ship, Projectile, 60, 10); --itemCircle(ship, Projectile, 75, 15); itemCircle(ship, Mine, 0, 2); end end --end shotgunner --sniper function shootSniper(ship, canShoot) local player = ship:getPlayerInfo(); if (ship:isModActive(Module.Shield)) then if (ship:getEnergy() ~= 0 and canShoot) then itemLine(ship, Projectile, 20); end ship:setEnergy(0); end end function checkScope(ship) local player = ship:getPlayerInfo(); local aiming = false; if (ship:isModActive(Module.Sensor)) then aiming = true; ship:setVel(point.new(0,0)); --draw line local item = nil; if (registered[player][3] == nil) then registered[player][3] = {}; end if (registered[player][3][1] == nil) then item = LineItem.new(); item:setTeam(ship:getTeamIndex()); item:setGlobal(true); --Left off here. Get geom of line then add item to game item:setGeom(lineOfSight(ship,5,1000)); bf:addItem(item); registered[player][3][1] = item; else item = registered[player][3][1]; --logprint(item); item:setGeom(lineOfSight(ship,5,1000)); end return true; end if (aiming == false and registered[player][3] ~= nil) then clearItems(registered[player][3]); registered[player][3] = nil; end return false; end --end sniper --tunneler function dig(ship) local player = ship:getPlayerInfo(); local aiming = false; if (ship:isModActive(Module.Cloak)) then if (registered[player][1] == 1) then registered[player][1] = 2; registered[player][4] = ship:getPos(); end ship:setEnergy(ship:getEnergy()-.009); return; else if (registered[player][1] == 2) then --make portal local item = nil; if (registered[player][3] == nil) then registered[player][3] = {}; end if (registered[player][3][1] == nil) then --make a new teleport item = Teleporter.new(); --Left off here. Get geom of line then add item to game item:setGeom(registered[player][4],ship:getPos()); bf:addItem(item); registered[player][3][1] = item; else item = registered[player][3][1]; --logprint(item); if (placeFree(registered[player][4],.2*255) and placeFree(ship:getPos(),.2*255)) then item:setGeom(registered[player][4],ship:getPos()); end end end registered[player][1] = 1; end end --end tunneler --end classes --events function onTick(delta) --do shotgun explosions for k,v in pairs(bombs) do if (v ~= nil and v[1] ~= nil) then v[2] = v[2] - delta; if (v[2] < 1) then v[2] = 500; -- 1/2 second itemCircle(v[4], Burst, 90-(40*v[3]), 8-(3*v[3])); v[3] = v[3] - 1; if (v[3] < 1) then v[1] = nil; v = nil; end end end end --do ship classes for k,v in pairs(registered) do if (v ~= nil) then local ship = v[2]:getShip(); --if they are a rookie if (v[5] == "rke") then --set their loadout local loadout = {Weapon.Phaser,Weapon.Phaser,Weapon.Phaser,Module.Turbo,Module.Turbo}; ship:setLoadout(loadout); ship:setLoadoutNow(loadout); --rookie max energy if (ship:getEnergy() > .15) then ship:setEnergy(.15); end --if they are a cloak elseif (v[5] == "clk") then --set their loadout local loadout = {Weapon.SpyBug,Weapon.SpyBug,Weapon.SpyBug,Module.Cloak,Module.Cloak}; ship:setLoadout(loadout); ship:setLoadoutNow(loadout); --Slow cloaking cloakSave(ship); --if they are a flame elseif (v[5] == "flm") then --set their loadout local loadout = {Weapon.Phaser,Weapon.Phaser,Weapon.Phaser,Module.Shield,Module.Shield}; ship:setLoadout(loadout); ship:setLoadoutNow(loadout); --flame max energy if (ship:getEnergy() > .5) then ship:setEnergy(.5); end --flame thrower throwFire(ship); --if they are a medic elseif (v[5] == "med") then --set their loadout local loadout = {Weapon.SpyBug,Weapon.SpyBug,Weapon.SpyBug,Module.Cloak,Module.Repair}; ship:setLoadout(loadout); ship:setLoadoutNow(loadout); --medkit superHeal(ship); --if they are a sniper elseif (v[5] == "snp") then --set their loadout local loadout = {Weapon.Phaser,Weapon.Phaser,Weapon.Phaser,Module.Sensor,Module.Shield}; ship:setLoadout(loadout); ship:setLoadoutNow(loadout); --sniper max energy if (ship:getEnergy() > .2) then ship:setEnergy(.2); end --show scope line local aiming = checkScope(ship); --now are they shooting? shootSniper(ship, aiming); --if they are a shotgunner elseif (v[5] == "sht") then --set their loadout local loadout = {Weapon.Triple,Weapon.Triple,Weapon.Burst,Module.Turbo,Module.Cloak}; ship:setLoadout(loadout); ship:setLoadoutNow(loadout); --shotgunner max energy if (ship:getEnergy() > .25) then ship:setEnergy(.25); end --explode kamikaze(ship); --if they are a tunneler elseif (v[5] == "tun") then --set their loadout local loadout = {Weapon.Triple,Weapon.Triple,Weapon.Triple,Module.Turbo,Module.Cloak}; ship:setLoadout(loadout); ship:setLoadoutNow(loadout); --tunneler max energy if (ship:getEnergy() > .7) then ship:setEnergy(.7); end --dig tunnel dig(ship); end end end end function onShipSpawned(ship) local player = ship:getPlayerInfo(); local name = player:getName(); if(ship:getObjType() == ObjType.Robot and name ~= "Beelzebot") then logprint("Not a Beelzebot!"); ship:removeFromGame(); --bf:addItem(Robot.new()); elseif (registered[player] == nil) then registered[player] = {1,player,{},false,"rke","rke"}; end end function onShipKilled(ship) if (registered[ship:getPlayerInfo()] ~= nil) then if (registered[ship:getPlayerInfo()][3] ~= nil) then clearItems(registered[ship:getPlayerInfo()][3]); end registered[ship:getPlayerInfo()] = nil; end end function onShipEnteredZone(ship, zone, zoneType, zoneId) --goalzone actions --this should be loadout zone, but currently they don't work with this event if (zoneType == ObjType.LoadoutZone) then local player = ship:getPlayerInfo(); if (zone:getTeamIndex() == ship:getTeamIndex() and registered[player][5] ~= registered[player][6]) then if (registered[player][3] ~= nil) then clearItems(registered[player][3]); end registered[player][5] = registered[player][6]; registered[player][1] = 1; end end end function onMsgReceived(message, sender, messageIsGlobal) message = message:lower(); logprint(message); local name = sender:getName(); if (message == "help") then levelgen:privateMsg('Type in the name of a class to change yours... for example "rke" is a rookie', name); levelgen:privateMsg('"med" and "tun" (medic and tunneler) are support classes.', name); levelgen:privateMsg('"sht" and "flm" (shotgunner and flame) are attack classes.', name); levelgen:privateMsg('"clk" and "snp" (cloak and sniper) are rogue classes.', name); elseif (message == "me") then if (registered[sender] ~= nil) then levelgen:privateMsg(registered[sender][5], name); else levelgen:privateMsg("rke", name); end elseif (message == "spt") then levelgen:privateMsg('"med" for medic.', name); levelgen:privateMsg('"tun" for tunneler.', name); elseif (message == "atk") then levelgen:privateMsg('"sht" for shotgunner.', name); levelgen:privateMsg('"flm" for flame.', name); elseif (message == "rog") then levelgen:privateMsg('"clk" for cloak.', name); levelgen:privateMsg('"snp" for sniper.', name); elseif (message == "clk") then registered[sender][6] = "clk"; levelgen:privateMsg('Ready to change loadout. Visit base LoadoutZone to change.', name); levelgen:privateMsg('Cloaks are a stealthy class. Cloaking takes no energy.', name); levelgen:privateMsg('They make mines when they become visible', name); elseif (message == "flm") then registered[sender][6] = "flm"; levelgen:privateMsg('Ready to change loadout. Visit base LoadoutZone to change.', name); levelgen:privateMsg('Flames are a close combat class.', name); levelgen:privateMsg('They have a short-range flamethrower.', name); elseif (message == "rke") then registered[sender][6] = "rke"; levelgen:privateMsg('Ready to change loadout. Visit base LoadoutZone to change.', name); levelgen:privateMsg('Rookies have a phaser and boost module;', name); levelgen:privateMsg('They don\'t do much else.', name); elseif (message == "med") then registered[sender][6] = "med"; levelgen:privateMsg('Ready to change loadout. Visit base LoadoutZone to change.', name); levelgen:privateMsg('Medics are a support class', name); levelgen:privateMsg('They can place spybugs and heal units', name); elseif (message == "snp") then registered[sender][6] = "snp"; levelgen:privateMsg('Ready to change loadout. Visit base LoadoutZone to change.', name); levelgen:privateMsg('Snipers have a phaser and a sniper beam;', name); levelgen:privateMsg('module#1 is the laser scope, #2 fires the beam', name); elseif (message == "sht") then registered[sender][6] = "sht"; levelgen:privateMsg('Ready to change loadout. Visit base LoadoutZone to change.', name); levelgen:privateMsg('Shotgunners are a kamikaze unit.', name); levelgen:privateMsg('Run (boost), Gun (triple), Explode (cloak)', name); elseif (message == "tun") then registered[sender][6] = "tun"; levelgen:privateMsg('Ready to change loadout. Visit base LoadoutZone to change.', name); levelgen:privateMsg('Tunnelers build portals using cloak', name); levelgen:privateMsg('you can\'t build next to walls though.', name); levelgen:privateMsg('WARNING: cloak uses more energy than normal.', name); else levelgen:privateMsg('Command not understood. Type "help" for more info', name); end end --end events --[13:06] I'd advise using string.find instead of name == "blah --[13:07] for the .0 case function main() for i=1,50 do logprint(''); end subscribe(Event.Tick); subscribe(Event.ShipSpawned); subscribe(Event.ShipKilled); subscribe(Event.ShipEnteredZone); subscribe(Event.MsgReceived); end