Advertisement
Janne252

COH2 Custom map script: Tunnel system

Mar 22nd, 2014
280
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 16.77 KB | None | 0 0
  1. function OnInitID()
  2.     -- [[ Markers ]]
  3.     mkr_hold_passengers = Marker_FromName("mkr_hold_passengers","Ability")
  4.     mkr_tunnel1_a = Marker_FromName("mkr_tunnel1_a","Ability")
  5.     mkr_tunnel1_b = Marker_FromName("mkr_tunnel1_b","Ability")
  6.  
  7.     -- [[ Squad Groups ]]
  8.  
  9.     -- [[ Entity Groups ]]
  10.     --[[
  11.     ***********************************************
  12.     Virtual Tunnels v1.0 By Janne "Janne252" Varjo
  13.    
  14.     - This system can be used to create virtual tunnels. The travelling squad is set invisible during the transport and set to
  15.     visible again after the transport.
  16.     - Each tunnel can be configured with:
  17.         - points: Tunnel entry & exit markers in a table.
  18.         - travelTime: How many seconds it takes to transport a squad from point_a to point_b or vice versa.
  19.         - lockedToTeam: Only specified team can use the tunnel. Use "both" to allow all teams.
  20.         - simultaneousTransport: Allow transporting multiple squads at the same time. Set to false to allow only one squad to transport at a time.
  21.         - lockForTeamDuringTransport: Allow transporting team 1 and 2 units in the tunnel at the same time.
  22.         - allowInfantry: Allow transporting infantry squads.
  23.         - allowVehicles: Allow transporting vehicle squads.
  24.         - allowATGuns: Allow transporting AT-Gun squads.
  25.         - id: Unique id for the tunnel.
  26.     - In addition there are other global settings, descbribed below:
  27.     --]]
  28.        
  29.     --GLOBAL CONFIG
  30.         -- How far squad must be from the tunnel entrance to allow squad to use the tunnel again (prevents resonance)
  31.         g_registerExitAt = 6
  32.         -- How far from the tunnel entrance squad moves after the transportation
  33.         g_moveToAfterTransport = 10
  34.         -- How many times squad is told to move to the tunnel door until forced to move
  35.         g_moveTreshold = 25
  36.         -- How many meters foward from the tunnel door vehicles are spawned
  37.         g_vehicleForwardSpawn = 2
  38.         -- How many meters further vehicles are detected to begin the transport (vehicles cannot get as close to tunnel doors as infantry can)
  39.         g_vehicleDetectIncrease = 2
  40.         -- Marker for holding passengers during transport
  41.         g_holdPassengersMarker = mkr_hold_passengers
  42.         --Tunnel configration
  43.         g_tunnels = {
  44.             {
  45.                 points = {mkr_tunnel1_a, mkr_tunnel1_b},
  46.                 travelTime = 5,
  47.                 lockedToTeam = "both",
  48.                 simultaneousTransport = true,
  49.                 lockForTeamDuringTransport = true,
  50.                 allowInfantry = true,
  51.                 allowVehicles = false,
  52.                 allowATGuns = false,
  53.                 allowTeamWeapons = false,
  54.                 id = 1,
  55.             },  
  56.         }
  57.     --END OF GLOBAL CONFIG
  58.  
  59.     -- Global variables, data holders
  60.     sg_tunnel = SGroup_CreateIfNotFound("sg_tunnel")
  61.     sg_blah = SGroup_CreateIfNotFound("sg_blah")
  62.     g_in_tunnel_squads = {}
  63.     g_fancyDespawn = {}
  64.     g_fancySpawn = {}
  65.     g_debug = true
  66.     g_text = ""
  67.     g_floodTimer = 0
  68.     msg("Tunnel system intitialized with "..table.getn(g_tunnels).." tunnels.")
  69.     -- System initialization and startup
  70.     Rule_Add(MonitorTunnels)
  71.     Rule_Add(FancyDespawnManager)
  72.     Rule_AddInterval(FancySpawnManager, 0.4)    
  73. end
  74.  
  75. function MonitorTunnels()
  76. --[[
  77.     - Monitors tunnels configured in g_tunnels
  78.     - Performs actions to squads based on the config
  79. --]]
  80.     for key, tunnel in ipairs(g_tunnels) do
  81.         for t_key, point in ipairs(tunnel.points) do
  82.             for i = 1, World_GetPlayerCount() do
  83.                 local player = World_GetPlayerAt(i)
  84.                 SGroup_Clear(sg_tunnel)
  85.                 World_GetSquadsNearMarker(player, sg_tunnel, point, OT_Player)
  86.                 SGroup_ForEach(sg_tunnel,
  87.                     function(sgid, idx, squad)
  88.                         if check_NotInTunnel(squad) and not Squad_IsInHoldSquad(squad) then
  89.                             g_floodTimer = g_floodTimer + 1
  90.                             local owner = Squad_GetPlayerOwner(squad)
  91.                             local team = Player_GetTeam(owner)
  92.                             if (tunnel.lockedToTeam == team or tunnel.lockedToTeam == "both") then
  93.                                 if (not tunnelHasTransports(tunnel.id) or tunnel.simultaneousTransport) then
  94.                                     if (tunnel.allowVehicles or not Squad_IsVehicle(squad)) then
  95.                                         if (tunnel.allowATGuns or not Squad_IsAtGun(squad)) then
  96.                                             if (tunnel.allowTeamWeapons or not Squad_IsTeamWeapon(squad)) then
  97.                                                 if (tunnel.allowInfantry or Squad_IsVehicle(squad)) then
  98.                                                     local ownerTeam = getCurrentTunnelOwner(tunnel.id)
  99.                                                     if ownerTeam == "world" or ownerTeam == Player_GetTeam(owner) or tunnel.lockForTeamDuringTransport == false then
  100.                                                         msg("despawning a squad with count "..Squad_Count(squad))
  101.                                                         local controlGroup = -1
  102.                                                         if Player_GetID(Game_GetLocalPlayer()) == Player_GetID(owner) then
  103.                                                             SGroup_Clear(sg_blah)
  104.                                                             Misc_GetSelectedSquads(sg_blah, false)
  105.                                                             if not SGroup_IsEmpty(sg_blah) then
  106.                                                                 Camera_MoveTo(Util_GetOffsetPosition(Camera_GetCurrentTargetPos(), OFFSET_FRONT, 1))
  107.                                                             end
  108.                                                             controlGroup = Misc_GetSquadControlGroup(squad)
  109.                                                             msg("seting controlgroup to "..controlGroup)
  110.                                                         end
  111.                                                         Squad_DeSpawnFancy(squad, point)
  112.                                                         _squad = {
  113.                                                             id = Squad_GetGameID(squad),
  114.                                                             destination = getDestination(tunnel.points, point),
  115.                                                             travelled = false,
  116.                                                             travelTime = tunnel.travelTime,
  117.                                                             timer = 0,
  118.                                                             tunnelId = tunnel.id,
  119.                                                             spawnedCount = Squad_Count(squad),
  120.                                                             deSpawnedCount = 0,
  121.                                                             startedSpawning = false,
  122.                                                             fullySpawned = false,
  123.                                                             fullyDespawned = false,
  124.                                                             owner = Squad_GetPlayerOwner(squad),
  125.                                                             controlGroup = controlGroup,
  126.                                                         }
  127.                                                         table.insert(g_in_tunnel_squads, _squad)
  128.                                                     else
  129.                                                         msg("Tunnel is currently owned by team "..ownerTeam..", team "..Player_GetTeam(owner).." is not permitted!", g_floodTimer)
  130.                                                     end
  131.                                                 else
  132.                                                     msg("squad is infantry, infantry transports not permitted!", g_floodTimer)
  133.                                                 end
  134.                                             else
  135.                                                 msg("squad is Team Weapon, Team weapon squad transports not permitted!", g_floodTimer)
  136.                                             end
  137.                                         else
  138.                                             msg("squad is AT-Gun, AT-Gun transports not permitted!", g_floodTimer)
  139.                                         end
  140.                                     else
  141.                                         msg("squad is vehicle, vehicle transports not permitted!", g_floodTimer)
  142.                                     end
  143.                                 else
  144.                                     msg("Tunnel is occupied, simultaneous transporting is not permitted!", g_floodTimer)
  145.                                 end
  146.                             else
  147.                                 msg("Tunnel is locked to team "..tunnel.lockedToTeam.." team "..team.." is not permitted!", g_floodTimer)
  148.                             end
  149.                         end
  150.                     end
  151.                 )
  152.             end
  153.         end
  154.     end
  155.    
  156.     for key, _squad in ipairs(g_in_tunnel_squads) do
  157.         if Squad_IsValid(_squad.id) and _squad.fullyDespawned then
  158.             local squad = Squad_FromWorldID(_squad.id)
  159.             _squad.timer = _squad.timer + 1
  160.             if _squad.timer % 10 == 0 and _squad.timer <= (_squad.travelTime * 8) then
  161.                 msg("timer is now ".._squad.timer)
  162.             end
  163.             if _squad.timer >= _squad.travelTime * 8 and not _squad.travelled and not _squad.startedSpawning then
  164.                 _squad.startedSpawning = true
  165.                 msg("starting to spawn a squad")
  166.                 Squad_SpawnFancy(squad, _squad)
  167.             end
  168.             if _squad.startedSpawning and not _squad.travelled then
  169.                 if _squad.fullySpawned then
  170.                     msg("all squad members are spawned")
  171.                     _squad.travelled = true
  172.                 end
  173.             end
  174.             if _squad.travelled then
  175.                 if Squad_DistanceToIsGreater(squad, Marker_GetPosition(_squad.destination), g_registerExitAt) then
  176.                     msg("squad is far enough from dest")
  177.                     table.remove(g_in_tunnel_squads, key)
  178.                 end
  179.             end
  180.         elseif not Squad_IsValid(_squad.id) then
  181.             msg("removing, squad is invalid!")
  182.             table.remove(g_in_tunnel_squads, key)
  183.         end
  184.     end
  185. end
  186.  
  187. function tunnelHasTransports(tunnelId)
  188.     -- Used to check whether or not a tunnel with tunnelId has squads in it.
  189.     for key, value in ipairs(g_in_tunnel_squads) do
  190.         if value.tunnelId == tunnelId and not value.travelled then
  191.             return true
  192.         end
  193.     end
  194.     return false
  195. end
  196.  
  197. function getCurrentTunnelOwner(tunnelId)
  198.     -- Used to return the owner of the squad in the tunnel.
  199.     for key, value in ipairs(g_in_tunnel_squads) do
  200.         if value.tunnelId == tunnelId then
  201.             return Player_GetTeam(value.owner)
  202.         end
  203.     end
  204.     return "world"
  205. end
  206.  
  207. function Squad_DistanceToIsGreater(squad, pos, distance)
  208.     -- Used to check if all entities in a squad are at a certain distance of a pos
  209.     for n = 1, Squad_Count(squad) do
  210.         local entity = Squad_EntityAt(squad, n-1)
  211.         local _distance = World_DistancePointToPoint(Entity_GetPosition(entity), pos)
  212.         if _distance < distance then
  213.             return false
  214.         end
  215.     end
  216.     return true
  217. end
  218.  
  219. function Squad_SpawnFancy(squad, _squad)
  220.     -- Used to spawn despawned squads in a Fancy way (coming out of the tunnel doors one by one)
  221.     local movePos = Marker_GetPosition(_squad.destination)
  222.     Squad_SetPosition(squad, movePos, movePos)
  223.     local squad_count = Squad_Count(squad)
  224.     for n = 1, Squad_Count(squad) do
  225.         local entity = Squad_EntityAt(squad, n-1)
  226.         local _entity = {
  227.             id = Entity_GetGameID(entity),
  228.             destination = _squad.destination,
  229.             squad = Squad_GetGameID(squad),
  230.             moveAttempts = 0,
  231.         }
  232.         table.insert(g_fancySpawn, _entity)
  233.     end
  234.     SGroup_Clear(sg_blah)
  235.     Squad_GetSquadsHeld(squad, sg_blah)
  236.     SGroup_ForEach(sg_blah,
  237.         function(sgid, idx, squad)
  238.             Squad_SpawnFancy(squad, _squad)
  239.         end
  240.     )
  241. end
  242.  
  243. function FancySpawnManager()
  244.     -- Used to control fancy spawning
  245.     local hasSpawned = false
  246.     for key, _entity in ipairs(g_fancySpawn) do
  247.         if not hasSpawned then
  248.             hasSpawned = true
  249.             if Entity_IsValid(_entity.id) then
  250.                 local entity = Entity_FromWorldID(_entity.id)
  251.                 UI_EnableEntitySelectionVisuals(entity, true)
  252.                 UI_EnableEntityMinimapIndicator(entity, true)
  253.                 local squad = Squad_FromWorldID(_entity.squad)
  254.                 local spawnPos = Marker_GetPosition(_entity.destination)
  255.                 local moveToPos = Util_GetOffsetPosition(_entity.destination, OFFSET_FRONT, g_moveToAfterTransport)
  256.                 if Squad_IsVehicle(squad) then
  257.                     spawnPos = Util_GetOffsetPosition(_entity.destination, OFFSET_FRONT, g_vehicleForwardSpawn)
  258.                 end
  259.                 _verifySpawn(entity, _entity, squad, spawnPos, moveToPos, key)
  260.             else
  261.                 msg("!! entity is not valid (spawn), not going to spawn")
  262.             end
  263.             table.remove(g_fancySpawn, key)
  264.         else
  265.             break
  266.         end
  267.     end
  268. end
  269.  
  270. function _verifySpawn(entity, _entity, squad, spawnPos, moveToPos, key)
  271.     -- Used to perform the actual fancy spawn actions
  272.     Entity_SetPosition(entity, spawnPos)
  273.     Entity_SetHeading(entity, Marker_GetDirection(_entity.destination), false)
  274.     Entity_VisHide(entity, false)
  275.     Entity_SimHide(entity, false)
  276.     Cmd_Move(Squad_GetSGroup(squad), moveToPos)
  277.     for k, v in ipairs(g_in_tunnel_squads) do
  278.         if v.id == _entity.squad then
  279.             v.spawnedCount = v.spawnedCount + 1
  280.             v.deSpawnedCount = v.deSpawnedCount - 1
  281.             msg("+ entity spawnCount, deSpawnedCount = "..v.spawnedCount..", "..v.deSpawnedCount.." ["..BP_GetName(Entity_GetBlueprint(entity)).."]")
  282.             if v.deSpawnedCount == 0 then
  283.                 v.fullySpawned = true
  284.                 msg("Fully spawned!")
  285.                 EnableSquad(squad)
  286.                 local owner = Squad_GetPlayerOwner(squad)
  287.                 if Player_GetID(Game_GetLocalPlayer()) == Player_GetID(owner) then
  288.                     if _squad.controlGroup > -1 then
  289.                         Misc_SetSquadControlGroup(squad, _squad.controlGroup)
  290.                         msg("getting controlgroup ".._squad.controlGroup)
  291.                     end
  292.                 end
  293.             end
  294.         end
  295.     end
  296. end
  297.  
  298. function EnableSquad(squad)
  299.     local sg_squad = Squad_GetSGroup(squad)
  300.     Squad_SetInvulnerable(squad, false, -1)
  301.     SGroup_SetSelectable(sg_squad, true)
  302.     SGroup_EnableUIDecorator(sg_squad, true)
  303.     SGroup_EnableMinimapIndicator(sg_squad, true)
  304.     Modify_SightRadius(sg_squad, 1000000)  
  305.     SGroup_Clear(sg_blah)
  306.     Squad_GetSquadsHeld(squad, sg_blah)
  307.     SGroup_ForEach(sg_blah,
  308.         function(sgid, idx, squad)
  309.             EnableSquad(squad)
  310.         end
  311.     )
  312. end
  313.  
  314. function DisableSquad(squad)
  315.     local sg_squad = Squad_GetSGroup(squad)
  316.     Squad_SetInvulnerable(squad, true, -1)
  317.     SGroup_SetSelectable(sg_squad, false)
  318.     SGroup_EnableUIDecorator(sg_squad, false)
  319.     SGroup_EnableMinimapIndicator(sg_squad, false)
  320.     Modify_SightRadius(sg_squad, 1/1000000)
  321.     SGroup_Clear(sg_blah)
  322.     Squad_GetSquadsHeld(squad, sg_blah)
  323.     SGroup_ForEach(sg_blah,
  324.         function(sgid, idx, squad)
  325.             DisableSquad(squad)
  326.         end
  327.     )
  328. end
  329.  
  330. function Squad_DeSpawnFancy(squad, pos)
  331.     -- used to despawn squads in a fancy way (moving to the tunnel doors one by one)
  332.     DisableSquad(squad)
  333.     local squad_count = Squad_Count(squad)
  334.     for n = 1, Squad_Count(squad) do
  335.         local entity = Squad_EntityAt(squad, n-1)
  336.         local _entity = {
  337.             id = Entity_GetGameID(entity),
  338.             destination = pos,
  339.             squad = Squad_GetGameID(squad),
  340.             moveAttempts = 0,
  341.         }
  342.         table.insert(g_fancyDespawn, _entity)
  343.     end
  344.     SGroup_Clear(sg_blah)
  345.     Squad_GetSquadsHeld(squad, sg_blah)
  346.     SGroup_ForEach(sg_blah,
  347.         function(sgid, idx, squad)
  348.             Squad_DeSpawnFancy(squad, pos)
  349.         end
  350.     )
  351. end
  352.  
  353. function FancyDespawnManager()
  354.     -- Used to control fancy despawning
  355.     for key, _entity in ipairs(g_fancyDespawn) do
  356.         if Entity_IsValid(_entity.id) then
  357.             local entity = Entity_FromWorldID(_entity.id)
  358.             UI_EnableEntitySelectionVisuals(entity, false)
  359.             UI_EnableEntityMinimapIndicator(entity, false)
  360.             local distance = World_DistancePointToPoint(Entity_GetPosition(entity), Marker_GetPosition(_entity.destination))
  361.             --msg("distance: "..distance)
  362.             local squad = Squad_FromWorldID(_entity.squad)
  363.             local increasedSearch = 0
  364.             if Squad_IsVehicle(squad) then
  365.                 increasedSearch = g_vehicleDetectIncrease
  366.             end
  367.             if distance < (1 + increasedSearch) then
  368.                 _verifyDeSpawn(entity, _entity, squad, key)
  369.             else
  370.                 --Cmd_Move(Squad_GetSGroup(Squad_FromWorldID(_entity.squad)), Marker_GetPosition(_entity.destination))
  371.                 _entity.moveAttempts = _entity.moveAttempts + 1
  372.                 if _entity.moveAttempts >= g_moveTreshold then
  373.                     msg("force deSpawning")
  374.                     Entity_SetPosition(entity, Marker_GetPosition(_entity.destination))
  375.                     _verifyDeSpawn(entity, _entity, squad, key)
  376.                 end
  377.             end
  378.         else
  379.             msg("removing from despawn, invalid entity")
  380.             table.remove(g_fancyDespawn, key)
  381.         end
  382.     end
  383. end
  384.  
  385. function _verifyDeSpawn(entity, _entity, squad, key)
  386.     -- used to perform the actual despawn actions
  387.     Entity_VisHide(entity, true)
  388.     Entity_SimHide(entity, true)
  389.     for k, v in ipairs(g_in_tunnel_squads) do
  390.         if v.id == _entity.squad then
  391.             v.spawnedCount = v.spawnedCount - 1
  392.             v.deSpawnedCount = v.deSpawnedCount + 1
  393.             msg("- entity spawnCount, deSpawnedCount = "..v.spawnedCount..", "..v.deSpawnedCount.." ["..BP_GetName(Entity_GetBlueprint(entity)).."]")
  394.             if v.spawnedCount == 0 then
  395.                 v.fullyDespawned = true
  396.                 msg("Fully DeSpawned!")
  397.                 Squad_SetPosition(squad, Marker_GetPosition(g_holdPassengersMarker), Util_GetOffsetPosition(Squad_GetPosition(squad), OFFSET_FRONT, 4))
  398.                 Cmd_Stop(Squad_GetSGroup(squad))
  399.             end
  400.         end
  401.     end
  402.     table.remove(g_fancyDespawn, key)
  403. end
  404.  
  405. function getDestination(tunnel, point)
  406.     -- Used to get x from table {x, y} if y is selected and vice versa
  407.     for key, value in ipairs(tunnel) do
  408.         if value ~= point then
  409.             msg("destination: "..Marker_GetName(value))
  410.             return value
  411.         end
  412.     end
  413.     msg("destination: same")
  414.     return point
  415. end
  416.  
  417. function check_NotInTunnel(squad)
  418.     -- Used to check if squad is not in a tunnel
  419.     for key, _squad in ipairs(g_in_tunnel_squads) do
  420.         if _squad.id == Squad_GetGameID(squad) then
  421.             return false
  422.         end
  423.     end
  424.     return true
  425. end
  426.  
  427. function Squad_GetSGroup(squad)
  428.     -- Used to return a temporaly sgroup for performing quick SGroup only actions for a squad
  429.     local sg_temptunnel = SGroup_CreateIfNotFound("sg_temptunnel")
  430.     SGroup_Clear(sg_temptunnel)
  431.     SGroup_Add(sg_temptunnel, squad)
  432.     return sg_temptunnel
  433. end
  434.  
  435. function Entity_GetEGroup(entity)
  436.     -- Used to return a temporaly egroup for performing quick EGroup only actions for an entity
  437.     local eg_temptunnel = EGroup_CreateIfNotFound("eg_temptunnel")
  438.     EGroup_Clear(eg_temptunnel)
  439.     EGroup_Add(eg_temptunnel, entity)
  440.     return eg_temptunnel
  441. end
  442.  
  443. function Squad_IsVehicle(squad)
  444.     -- Used to check if squad is a vehicle
  445.     local entity = Squad_EntityAt(squad, 0)
  446.     if Entity_IsOfType(entity, "vehicle") and not Entity_IsOfType(entity, "team_weapon") then
  447.         return true
  448.     end
  449.     return false
  450. end
  451.  
  452. function Squad_IsTeamWeapon(squad)
  453.     -- Used to check if squad is a team weapon squad
  454.     for n = 1, Squad_Count(squad) do
  455.         local entity = Squad_EntityAt(squad, n-1)
  456.         if Entity_IsOfType(entity, "team_weapon") then
  457.             return true
  458.         end
  459.     end
  460.     return false
  461. end
  462.  
  463. function Squad_IsAtGun(squad)
  464.     -- Used to check if squad is an AT-Gun squad
  465.     for n = 1, Squad_Count(squad) do
  466.         local entity = Squad_EntityAt(squad, n-1)
  467.         if Entity_IsOfType(entity, "at_gun") then
  468.             return true
  469.         end
  470.     end
  471.     return false
  472. end
  473.  
  474. function msg(text, floodTimer)
  475.     -- used to print debug messages
  476.     if not floodTimer then floodTimer = 10 end
  477.     if g_debug then
  478.         if floodTimer % 10 == 0 then
  479.             dr_clear("UI2")
  480.             dr_setautoclear("UI2", false)
  481.             g_text = text.."\n"..g_text
  482.             dr_text2d("UI2", 0.715, 0.02, g_text, 255, 0, 0)  
  483.         end
  484.     end
  485. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement