- Joined
- Jun 26, 2020
- Messages
- 1,921
I getting tired with the WE, I tried to improve the Lua version of my Unit Transmission system, but the game displays error when I wanna run the map, so what is wrong with this code?
Lua:
do -- version 1.1.0
--[[
Also requires the Lua Timer Utils. https://www.hiveworkshop.com/threads/lua-timerutils.316957/
How it works:
a value of type Transmission and use the function create like this:
local curr = Transmission.create([force toForce, any data])
"toForce" is the target force of the transmission
"data" is if you wanna save a value during the transmission
also you can set manually this values using:
curr:SetTargetForce(force toForce) This not assing a force, just move the players of the input to the actually target force, so using a function that creates a force
in the argument toForce will cause an object leak.
you can also save a value to use during the transmission using:
curr.Data = value
if you wanna add or remove a player or a force to the target force just use the normal functions ForceAddPlayer, ForceRemovePlayer and the added ForceAddForce, ForceRemoveForce
Then to add a dialogue line just do:
curr:AddLine(unit whichUnit, playercolor color, string unitName, sound soundHandle, string message, integer timeType, real timeVal, boolean wait) returns TransmissionElements
"whichUnit": The unit who do the dialogue line.
"color": The color of the unit in the dialogue (if you set this value to nil so then, if you have the StoreUnitColor library the unit will have their actual color, if not, it will have their owner color).
"unitName": The name of that unit.
"soundHandle": The sound that will be played during the dialogue line.
"message": What the unit will say.
"timeType": Is like the GUI function, you can use 0 (Transmission.ADD), 1 (Transmission.SET), 2 (Transmission.SUB), another value will make the wait time to 0.
"timeVal": Is like the GUI function, the normal duration of the transmission is the duration of the sound and you can edit the value depending of this and the previous value.
"wait": Is like the GUI function, if this is true the next transmission will be wait the time depending of the previous two values.
In case you don't wanna set a unit, but instead a unit-type you can use curr.AddLinebyId instead (default color BLACK)
Also you can add actions between the lines using the function:
curr:AddAction(real delay [, function actions])
"delay": If you wanna add a delay to the next action or line.
"actions": The function that will run, don't add nothing if you just wanna a delay.
If you wanna the action run in the exact moment a line is happening just set the delay to 0.00 and put it right before the line.
I have to say this steps are assinged an index by the order they were declared that is the number of the step.
You can also add an action to the end of the transmission (this function will run yes or yes even you skip the transmission) using:
curr:AddEnd(function func)
Where you can use the values curr = Transmission.instance to reffer to the actual instance, and with that use curr.Data if you stored one and curr.Skipped to detect
if the cinematic was skipped but if was skipped in the last line this value will remain false.
After set the lines the function
curr:Start()
To start the transmission, and to skip the transmission (the end function will run anyway) just press the ESC button,
(this will skip all the transmissions where the player is) but if the implied force has more than one player the process will continue
to the rest of players on that force (.toForce is empty). The transmission will end only if all the implied players skip the transmission (So if you use "All players"
probably you never won't skip the transmission) but you can use the function Force(player p) to have a force just for 1 player (Don't destroy those forces).
If you wanna you can also pause the transmission using:
curr:Stop(boolean fadeout [, real delay])
"fadeout" is to set you wanna end actual played sound with a fade out.
"delay" is if you wanna the transmission resume itself after a while
And to resume manually use:
curr:Resume()
Note: The transsmision and its elements are not stored after start it, they are recycled once the transmission ends.
Other members:
force toForce, to reffer the force to which it is addressed the transmission.
force OriginalTargetForce, if you edited the force toForce, you can have the original force with this.
player toPlayer, if the transmission is just for one player you can use this instead, in other case this will return the last added player. --(I don't know the order)
integer LineNumber, is more precise if you use the method AddSceneActions. Same as Transmission.instance.Elements.NumberLine
integer ActionNumber, is the number of the actions those are running. Same as Transmission.instance.Elements.NumberAction
integer StepNumber, is the number of the step that is running (line or actions). Same as Transmission.instance.Elements.NumberStep
boolean Paused, returns if the transmission is paused.
TransmissionElements Elements, to reffer to the elements instance of the actual step.
method AddSceneActions(function func)
If you wanna add an action that runs everytime an step (line or action except the end) is runned, this also can be a replace of .AddAction in some
moments if you compare the number of the step with StepNumber, to know if is a line or action use the member boolean IsLine
and if is true you can use the member integer LineNumber to know the number of the actual line.
This also runs before the action or line is runned, so you can use it to edit the current step.
method RemoveSceneActions(function func)
This remove the actions that you added before.
If you wanna set the elements by separated you can use the member
method AddStep(string whattype [, integer stepnumber]) returns TransmissionElements
This add an step in the 'stepnumber' place, 'whattype' only can be "line" and "action" and move the next steps and renum them.
The default value of stepnumber is the length quantity of steps added.
method RemoveStep(integer stepnumber)
This remove an step using the number of the step and move the next steps and renum them.
After add the step the returned value have their own members
unit Unit -- This is the unit who will be marked during the transmission (not who will apear in the transmission).
integer UnitType
playercolor Color
string Name
sound Sound
string Message
real Time
integer TimeType
boolean WillWait
real Delay
integer NumberLine
integer NumberAction
integer NumberStep
method SetActions(function func) This replace all the actions
method AddActions(function func) This add action without affecting the added actions
method GetActions() returns a Array<functions>
But if you wanna use this members using the number of the step use their "ByIndex" methods (these are members of Transmission not of TransmissionElements)
You have to do:
curr:Set$Name of the member$ByIndex(integer stepnumber, $type of the member$ value)
value = curr:Get$Name of the member$ByIndex(integer stepnumber) (Except WillWait and AddActions)
Example:
local curr = Transmission.create()
curr:AddStep("line") --is the step 1
curr:AddStep("action") --is the step 2
curr:SetUnitByIndex(1, <your unit>)
curr:SetActionsByIndex(2, <your actions>)
A replace of:
local curr = Transmission.create()
local what
what = curr:AddStep("line")
what:SetUnit(<your unit>)
what = curr:AddStep("action")
what:SetActions(<your actions>)
But if you wanna save the number of lines you can set default values (before than create the steps)
unit DefUnit
integer DefUnitType
playercolor DefColor
string DefName
sound DefSound
string DefMessage
real DefTime
integer DefTimeType
boolean DefWillWait
real DefDelay
Here are more members:
Array<TransmissionElements> Lines
Array<TransmissionElements> Actions
Array<TransmissionElements> Steps
]]--
--A function to use
local What_Force = {}
function IsForceEmpty(f)
if f then
local Temp = 0
ForForce(f, function ()
Temp = Temp + 1
end)
return Temp == 0
end
return true
end
function ForceAddForce(principal, other)
if not principal or not other then
return
else
ForForce(principal ,function ()
ForceAddPlayer(other, GetEnumPlayer())
end)
end
end
function ForceRemoveForce(principal, other)
if not principal or not other then
return
else
ForForce(principal ,function ()
ForceRemovePlayer(other,GetEnumPlayer())
end)
end
end
function Force(p)
return What_Force[GetPlayerId(p)]
end
function CheckType(v, t)
if type(t) ~= "string" then
error("Is this a joke?", 3)
end
if type(v) == t then
return true
elseif math.type(v) == t then
return true
else
if type(v) == "table" then
local mt = getmetatable(t)
local name = mt.__name
if t == name then
return true
end
end
end
error("Wrong type, expected: " .. t, 3)
end
-- This are the elements of each line transmission
TransmissionElementsMT = {
--[[
private:
table actions
]]
__index = function (t, k)
-- Define only what fields can have your object
if TransmissionElementsMT[k] then
return TransmissionElementsMT[k]
elseif k == "isline" or
k == "NumberStep" then
return rawget(t, k)
elseif k == "Unit" or
k == "UnitType" or
k == "Color" or
k == "Name" or
k == "Sound" or
k == "Message" or
k == "TimeType" or
k == "Time" or
k == "WillWait" or
k == "NumberLine" then
if not rawget(t, "isline") then
error("This is an action", 2)
end
return rawget(t, k)
elseif k == "Delay" or
k == "NumberAction" then
if rawget(t, "isline") then
error("This is a line", 2)
end
return rawget(t, k)
else
error("This field doesn't exist " .. tostring(k), 2)
end
end,
__newindex = function (t, k , v)
-- Define only what fields can have your object
if TransmissionElementsMT[k] then
error("You can't edit this method", 2)
elseif (k == "NumberStep" and CheckType(v, "integer")) then
rawset(t, k, v)
elseif k == "Unit" or
(k == "UnitType" and CheckType(v, "integer")) or
k == "Color" or
(k == "Name" and CheckType(v, "string")) or
k == "Sound" or
(k == "Message" and CheckType(v, "string")) or
(k == "TimeType" and CheckType(v, "integer")) or
(k == "Time" and CheckType(v, "number")) or
(k == "WillWait" and CheckType(v, "boolean")) or
(k == "NumberLine" and CheckType(v, "integer")) then
if not rawget(t, "isline") then
error("This is an action", 2)
end
rawset(t, k, v)
elseif (k == "Delay" and CheckType(v, "number")) or
(k == "NumberAction" and CheckType(v, "integer")) then
if rawget(t, "isline") then
error("This is a line", 2)
end
rawset(t, k, v)
elseif k == "isline" then
error("You can't edit a read-only field " .. tostring(k), 2)
else
error("You can't add new fields " .. tostring(k), 2)
end
end,
__name = "TransmissionElements",
__tostring = function (t)
local result = ""
if rawget(t, "isline") then
result = result .. "Unit: " .. tostring(t.Unit) .. "\n"
.. "UnitType: " .. tostring(t.UnitType) .. "\n"
.. "Color: " .. tostring(t.Color) .. "\n"
.. "Name: " .. t.Name .. "\n"
.. "Sound: " .. tostring(t.Sound) .. "\n"
.. "Message" .. t.Message .. "\n"
.. "TimeType: " .. tostring(t.TimeType) .. "\n"
.. "Time: " .. t.Time .. "\n"
.. "WillWait: " .. t.WillWait .. "\n"
else
result = result .. "Delay: " .. tostring(t.Delay) .. "\n"
for k, v in ipairs(rawget(t, "actions")) do
result = result .. "Action ".. k .. ": " .. tostring(v) .. "\n"
end
end
return result
end
}
function TransmissionElementsMT:SetActions(func)
if rawget(self, "isline") then
error("This is a line |cffff0000SetActions|r", 2)
end
rawset(self, "actions", {})
if func then
table.insert(rawget(self, "actions"), func)
end
end
function TransmissionElementsMT:AddActions(func)
if rawget(self, "isline") then
error("This is a line |cffff0000AddActions|r", 2)
-- Only add actions if func is not nil and self.actions was created previously
elseif not func then
return
elseif not rawget(self, "actions") then
error("Why do you wanna add \"more\" actions if there isn't even a trigger with actions?", 2)
else
table.insert(rawget(self, "actions"), func)
end
end
function TransmissionElementsMT:GetActions()
if rawget(self, "isline") then
error("This is a line |cffff0000GetActions|r", 2)
end
return rawget(self, "actions")
end
TransmissionElements = setmetatable({
create = function (whattype)
local self = setmetatable({}, TransmissionElementsMT)
if whattype == "line" then
rawset(self, "isline", true)
elseif whattype == "action" then
rawset(self, "isline", false)
else
error("Invalid type.", 2)
end
return self
end,
create_action = function (delay, func)
local self = TransmissionElements.create("action")
-- Now I can store functions :D
if not rawget(self, "actions") then
rawset(self, "actions", {})
end
if func then
table.insert(rawget(self, "actions"), func)
end
self.Delay = delay
return self
end,
create_line = function (whichUnit, whichColor, unitName, soundHandle, message, timeType, timeVal, wait)
local self = TransmissionElements.create("line")
self.Unit = whichUnit
self.Name = unitName
self.Sound = soundHandle
self.Message = message
self.TimeType = timeType
self.Time = timeVal
self.WillWait = wait
if not whichUnit then
self.UnitType = 0
if not whichColor then
if LIBRARY_StoreUnitColor then
self.Color = PLAYER_COLOR_BLACK
else
self.Color = ConvertPlayerColor(PLAYER_NEUTRAL_AGGRESSIVE)
end
else
self.Color = whichColor
end
else
self.UnitType = GetUnitTypeId(whichUnit)
if not whichColor then
if LIBRARY_StoreUnitColor then
self.Color = GetUnitColor(whichUnit)
else
self.Color = GetPlayerColor(GetOwningPlayer(whichUnit))
end
else
self.Color = whichColor
end
end
return self
end
}, {
__index = function (t, k)
if k == "create" or
k == "create_action" or
k == "create_line" then
return rawget(t, k)
else
error("This field don't exist " .. tostring(k), 2)
end
end,
__newindex = function (t, k, v)
-- Define only what fields can have your class
if true then
error("You can't add new fields " .. tostring(k), 2)
end
end,
__name = "TransmissionElements",
__tostring = function (t)
return "Class: TransmissionElements"
end
})
--*****************************************************
--********The actual struct of the transmission********
--*****************************************************
local LocalPlayer = nil
local AllInstances = {}
for i = 0, PLAYER_NEUTRAL_AGGRESSIVE do
AllInstances[Player(i)] = {}
end
TransmissionMT = {
--[[
private
boolean paused
TransmissionElements elements
boolean skipped
sound played
Array<functions> final
timer t
integer current
integer actual_line
integer actual_action
integer actual_step
boolean ended
Array<functions> scene
]]
__index = function (t, k)
-- Define only what fields can have your object
if TransmissionMT[k] then
return TransmissionMT[k]
elseif k == "toPlayer" or
k == "toForce" or
k == "OriginalTargetForce" or
k == "DefUnit" or
k == "DefUnitType" or
k == "DefColor" or
k == "DefName" or
k == "DefSound" or
k == "DefMessage" or
k == "DefTime" or
k == "DefTimeType" or
k == "DefWillWait" or
k == "DefDelay" or
k == "Data" or
k == "Steps" or
k == "Lines" or
k == "Actions" then
return rawget(t, k)
elseif k == "Paused" then
return rawget(t, "paused")
elseif k == "Skipped" then
return rawget(t, "skipped")
elseif k == "Elements" then
return rawget(t, "elements")
elseif k == "IsLine" then
return rawget(rawget(t, "elements"), "isline")
elseif k == "StepNumber" then
return rawget(t, "elements").NumberAction
elseif k == "ActionNumber" then
return rawget(t, "elements").NumberAction
elseif k == "LineNumber" then
return rawget(t, "elements").NumberLine
else
error("This field doesn't exist " .. tostring(k), 2)
end
end,
__newindex = function (t, k , v)
-- Define only what fields can have your object
if TransmissionMT[k] then
error("You can't edit this method")
elseif k == "toPlayer" or
k == "toForce" or
k == "OriginalTargetForce" or
k == "DefUnit" or
(k == "DefUnitType" and CheckType(v, "integer")) or
k == "DefColor" or
(k == "DefName" and CheckType(v, "string")) or
k == "DefSound" or
(k == "DefMessage" and CheckType(v, "string")) or
(k == "DefTime" and CheckType(v, "number")) or
(k == "DefTimeType" and CheckType(v, "integer")) or
(k == "DefWillWait" and CheckType(v, "boolean")) or
(k == "DefDelay" and CheckType(v, "number")) or
k == "Data" or
(k == "Steps" and CheckType(v, "table")) or
(k == "Lines" and CheckType(v, "table")) or
(k == "Actions" and CheckType(v, "table")) then
rawset(t, k, v)
elseif k == "Paused" or
k == "Skipped" or
k == "Elements" or
k == "IsLine" or
k == "StepNumber" or
k == "ActionNumber" or
k == "LineNumber" then
error("You can't edit a read-only field " .. tostring(k), 2)
else
error("You can't add new fields " .. tostring(k), 2)
end
end,
__len = function (t)
return #t.Steps
end,
__name = "Transmission",
__tostring = function (t)
local result = ""
for _, v in ipairs(t.Steps) do
result = result .. tostring(v)
end
return result
end
}
-- When the transmission ends
local function finish(self)
ReleaseTimer(rawget(self, "t"))
rawset(self, "ended", true)
if rawget(self, "final") then
Transmission.instance = self
for _, func in ipairs(rawget(self, "final")) do
func()
end
Transmission.instance = nil
rawset(self, "final", nil)
end
ForForce(self.toForce, function ()
for k, v in ipairs(AllInstances[GetEnumPlayer()]) do
if v == self then
table.remove(AllInstances[GetEnumPlayer()], k)
break
end
end
end)
DestroyForce(self.OriginalTargetForce)
DestroyForce(self.toForce)
self.Steps = nil
self.Lines = nil
self.Actions = nil
rawset(self, "scene", nil)
rawset(self, "elements", nil)
self.Data = nil
rawset(self, "played", nil)
self.toForce = nil
self.toPlayer = nil
self.t = nil
end
local function what_call(self)
rawset(self, "current", rawget(self, "current") + 1)
rawset(t, "elements", self.Steps[rawget(self, "current")])
if not rawget(self, "elements") or IsForceEmpty(self.toForce) then
-- If the cinematic was skipped just in the last line it won't be counted as skipped
rawset(self, "skipped", IsForceEmpty(self.toForce) and rawget(self, "elements"))
finish(self)
else
if rawget(rawget(self, "elements"), "isline") then
self:cinematic_line()
else
self:cinematic_actions()
end
end
end
local function callback()
what_call(GetTimerData())
end
-- Where the magic happens
function TransmissionMT:cinematic_line()
local alpha = 0
local delay = 0.00
local what = rawget(self, "elements")
if rawget(self, "scene") then
Transmission.instance = self
for _, func in ipairs(rawget(self, "scene")) do
func()
end
Transmission.instance = nil
end
rawset(self, "played", what.Sound)
bj_lastTransmissionDuration = GetTransmissionDuration(rawget(self, "played"), what.TimeType, what.Time)
if IsPlayerInForce(LocalPlayer, self.toForce) then
if rawget(self, "played") then
StartSound(rawget(self, "played"))
end
SetCinematicScene(what.UnitType, what.Color, what.Name, what.Message, bj_lastTransmissionDuration + bj_TRANSMISSION_PORT_HANGTIME, bj_lastTransmissionDuration)
alpha = 255
end
if what.Unit then
UnitAddIndicator(what.Unit, 255, 255, 255, alpha)
end
if what.WillWait then
delay = bj_lastTransmissionDuration
end
if delay > 0.00 then
TimerStart(rawget(self, "t"), delay, false, callback)
else
what_call(self)
end
end
function TransmissionMT:cinematic_actions()
local what = rawget(self, "elements")
Transmission.instance = self
if rawget(self, "scene") then
for _, func in ipairs(rawget(self, "scene")) do
func()
end
end
pcall(function ()
for _, func in ipairs(what:GetActions()) do
func()
end
end)
Transmission.instance = nil
if what.Delay > 0.00 then
TimerStart(rawget(self, "t"), what.Delay, false, callback)
else
what_call(self)
end
end
function TransmissionMT:Resume()
if rawget(self, "paused") then
rawset(self, "paused", false)
ResumeTimer(rawget(self, "t"))
if IsPlayerInForce(LocalPlayer, self.toForce) then
StartSound(rawget(self, "played"))
end
SetSoundOffsetBJ(TimerGetElapsed(rawget(self, "t")), rawget(self, "played")) -- In case of desync
end
end
function TransmissionMT:Stop(fadeout, delay)
CheckType(fadeout, "boolean")
if delay ~= nil then
CheckType(delay, "number")
end
rawset(self, "paused", true)
PauseTimer(rawget(self, "t"))
StopSound(rawget(self, "played"), false, fadeout)
if delay then
if delay>0.00 then
TimerStart(NewTimer(), delay, false, function ()
self:Resume()
ReleaseTimer()
end)
else
self:Resume()
warn("Why do you even use this method?, Ay.")
end
end
end
function TransmissionMT:Start()
-- If there is not a line or action so it just go to the end
rawset(self, "current", 0)
rawset(self, "elements", nil)
what_call(self)
end
-- Now I can save functions :D
function TransmissionMT:AddEnd(func)
CheckType(func, "function")
if not rawget(self, "final") then
rawset(self, "final", {})
end
table.insert(rawget(self, "final"), func)
end
-- To add an action everytime a line or action is runned
function TransmissionMT:AddSceneActions(func)
CheckType(func, "function")
if not rawget(self, "scene") then
rawset(self, "scene", {})
end
table.insert(rawget(self, "scene"), func)
end
-- But if you wanna remove it
function TransmissionMT:RemoveSceneActions(actions)
table.remove(rawget(self, "scene"), actions)
end
--To set and get the values using their step position
function TransmissionMT:SetUnitByIndex(stepnumber, value)
CheckType(stepnumber, "integer")
self.Steps[stepnumber].Unit = value
end
function TransmissionMT:GetUnitByIndex(stepnumber)
CheckType(stepnumber, "integer")
return self.Steps[stepnumber].Unit
end
function TransmissionMT:SetUnitTypeByIndex(stepnumber, value)
CheckType(stepnumber, "integer")
self.Steps[stepnumber].UnitType = value
end
function TransmissionMT:GetUnitTypeByIndex(stepnumber)
CheckType(stepnumber, "integer")
return self.Steps[stepnumber].UnitType
end
function TransmissionMT:SetColorByIndex(stepnumber, value)
CheckType(stepnumber, "integer")
self.Steps[stepnumber].Color = value
end
function TransmissionMT:GetColorByIndex(stepnumber)
CheckType(stepnumber, "integer")
return self.Steps[stepnumber].Color
end
function TransmissionMT:SetNameByIndex(stepnumber, value)
CheckType(stepnumber, "integer")
CheckType(value, "string")
self.Steps[stepnumber].Name = value
end
function TransmissionMT:GetNameByIndex(stepnumber)
CheckType(stepnumber, "integer")
return self.Steps[stepnumber].Name
end
function TransmissionMT:SetSoundByIndex(stepnumber, value)
CheckType(stepnumber, "integer")
self.Steps[stepnumber].Sound = value
end
function TransmissionMT:GetSoundByIndex(stepnumber)
CheckType(stepnumber, "integer")
return self.Steps[stepnumber].Sound
end
function TransmissionMT:SetMessageByIndex(stepnumber, value)
CheckType(stepnumber, "integer")
CheckType(value, "string")
self.Steps[stepnumber].Message = value
end
function TransmissionMT:GetMessageByIndex(stepnumber)
CheckType(stepnumber, "integer")
return self.Steps[stepnumber].Message
end
function TransmissionMT:SetTimeTypeByIndex(stepnumber, value)
CheckType(stepnumber, "integer")
CheckType(value, "integer")
self.Steps[stepnumber].TimeType = value
end
function TransmissionMT:GetTimeTypeByIndex(stepnumber)
CheckType(stepnumber, "integer")
return self.Steps[stepnumber].TimeType
end
function TransmissionMT:SetTimeByIndex(stepnumber, value)
CheckType(stepnumber, "integer")
CheckType(value, "number")
self.Steps[stepnumber].Time = value
end
function TransmissionMT:GetTimeByIndex(stepnumber)
CheckType(stepnumber, "integer")
return self.Steps[stepnumber].Time
end
function TransmissionMT:SetWillWaitByIndex(stepnumber, value)
CheckType(stepnumber, "integer")
CheckType(value, "boolean")
self.Steps[stepnumber].WillWait = value
end
function TransmissionMT:WillWaitByIndex(stepnumber)
CheckType(stepnumber, "integer")
return self.Steps[stepnumber].WillWait
end
function TransmissionMT:SetDelayByIndex(stepnumber, value)
CheckType(stepnumber, "integer")
CheckType(value, "number")
self.Steps[stepnumber].Delay = value
end
function TransmissionMT:GetDelayByIndex(stepnumber)
CheckType(stepnumber, "integer")
return self.Steps[stepnumber].Delay
end
function TransmissionMT:SetActionsByIndex(stepnumber, func)
CheckType(stepnumber, "integer")
CheckType(func, "function")
self.Steps[stepnumber].SetActions(func)
end
function TransmissionMT:GetActionsByIndex(stepnumber)
CheckType(stepnumber, "integer")
self.Steps[stepnumber].GetActions()
end
function TransmissionMT:AddActionsByIndex(stepnumber, func)
CheckType(stepnumber, "integer")
CheckType(func, "function")
self.Steps[stepnumber].AddActions(func)
end
--If you wanna remove a step
function TransmissionMT:RemoveStep(stepnumber)
CheckType(stepnumber, "integer")
local what = table.remove(self.Steps, stepnumber)
if rawget(what, "isline") then
for k, v in ipairs(self.Lines) do
if what == v then
table.remove(self.Lines, k)
break
end
end
rawset(self, "actual_line", #self.Lines)
for j = stepnumber, rawget(self, "actual_line") do
self.Lines[j].NumberLine = self.Lines[j].NumberLine - 1
end
else
for k, v in ipairs(self.Actions) do
if what == v then
table.remove(self.Actions, k)
break
end
end
rawset(self, "actual_action", #self.Actions)
for j = stepnumber, rawget(self, "actual_action") do
self.Actions[j].NumberAction = self.Steps[j].NumberAction - 1
end
end
rawset(self, "actual_step", #self.Steps)
for j = stepnumber, rawget(self, "actual_step") do
self.Steps[j].NumberStep = self.Steps[j].NumberStep - 1
end
end
-- To set a line with all the needed values (at the beggining)
function TransmissionMT:AddLine(whichUnit, whichColor, unitName, soundHandle, message, timeType, timeVal, wait)
CheckType(unitName, "string")
CheckType(message, "string")
CheckType(timeType, "integer")
CheckType(timeVal, "number")
CheckType(wait, "boolean")
local what = TransmissionElements.create_line(whichUnit, whichColor, unitName, soundHandle, message, timeType, timeVal, wait)
table.insert(self.Lines, what)
rawset(self, "actual_line", #self.Lines)
what.NumberLine = rawget(self, "actual_line")
table.insert(self.Steps, what)
rawset(self, "actual_step", #self.Steps)
what.NumberStep = rawget(self, "actual_step")
return what
end
function TransmissionMT:AddLineById(id, whichColor, unitName, soundHandle, message, timeType, timeVal, wait)
CheckType(id, "integer")
CheckType(unitName, "string")
CheckType(message, "string")
CheckType(timeType, "integer")
CheckType(timeVal, "number")
CheckType(wait, "boolean")
local what = self:AddLine(nil, whichColor, unitName, soundHandle, message, timeType, timeVal, wait)
what.UnitType = id
return what
end
-- To add an action and (maybe) a delay to the next action or line
function TransmissionMT:AddAction(delay, actions)
CheckType(delay, "number")
if actions ~= nil then
CheckType(actions, "function")
end
local what = TransmissionElements.create_action(delay, actions)
table.insert(self.Actions, what)
rawset(self, "actual_action", #self.Actions)
table.insert(self.Steps, what)
rawset(self, "actual_step", #self.Steps)
what.NumberStep = rawget(self, "actual_step")
return what
end
function TransmissionMT:AddStep(whattype, stepnumber)
CheckType(whattype, "string")
if stepnumber ~= nil then
CheckType(stepnumber, "integer")
end
local node = TransmissionElements.create(whattype)
if whattype == "line" then
node.Unit = self.DefUnit
node.UnitType = self.DefUnitType or 0
node.Color = self.DefColor
node.Name = self.DefName or ""
node.Sound = self.DefSound
node.Message = self.DefMessage or ""
node.Time = self.DefTime or 0.00
node.TimeType = self.DefTimeType or 1
node.WillWait = self.DefWillWait
if stepnumber then
table.insert(self.Lines, node)
rawset(self, "actual_line", #self.Lines)
node.NumberLine = self.actual_line
else
local i = 1
for j = stepnumber, 0, -1 do
if rawget(self.Steps[j], "isline") == true then
i = j + 1
break
end
end
table.insert(self.Lines, i, node)
rawset(self, "actual_line", #self.Lines)
for j = i + 1, rawget(self, "actual_line") do
self.Lines[j].NumberLine = self.Lines[j].NumberLine + 1
end
node.NumberLine = i
end
else
node.Delay = self.DefDelay or 0.00
if stepnumber then
table.insert(self.Actions, node)
rawset(self, "actual_action", #self.Actions)
node.NumberLine = rawget(self, "actual_action")
else
local i = 1
for j = stepnumber, 0, -1 do
if rawget(self.Steps[j], "isline") == false then
i = j + 1
break
end
end
table.insert(self.Actions, i, node)
rawset(self, "actual_action", #self.Actions)
for j = i + 1, rawget(self, "actual_action") do
self.Actions[j].NumberAction = self.Actions[j].NumberAction + 1
end
node.NumberAction = i
end
end
if stepnumber then
table.insert(self.Steps, stepnumber, node)
rawset(self, "actual_step", #self.Steps)
for j = stepnumber, rawget(self, "actual_step") do
self.Steps[j].NumberStep = self.Steps[j].NumberStep + 1
end
node.NumberStep = stepnumber
else
table.insert(self.Steps, node)
rawset(self, "actual_step", #self.Steps)
node.NumberStep = rawget(self, "actual_step")
end
return node
end
-- You can edit the target force and the data
function TransmissionMT:SetTargetForce(toForce)
if toForce and not IsForceEmpty(toForce) then
ForForce(toForce, function ()
local p = GetEnumPlayer()
self.toPlayer = p
ForceAddPlayer(self.toForce, p)
ForceAddPlayer(self.OriginalTargetForce, p)
table.insert(AllInstances[p], self)
end)
end
end
Transmission = setmetatable({
ADD = bj_TIMETYPE_ADD, -- 0
SET = bj_TIMETYPE_SET, -- 1
SUB = bj_TIMETYPE_SUB, -- 2
}, {
__index = function (t, k)
if k == "create" or
k == "ADD" or
k == "SET" or
k == "SUB" or
k == "instance" then
return rawget(t, k)
else
error("This field doesn't exist " .. tostring(k), 2)
end
end,
__newindex = function (t, k, v)
-- Define only what fields can have your class
if k == "ADD" or
k == "SET" or
k == "SUB" then
error("This value is a constant " .. tostring(k), 2)
elseif k == "instance" then
error("You can't edit a read-only field " .. tostring(k), 2)
else
error("You can't add new fields " .. tostring(k), 2)
end
end,
__name = "Transmission",
__tostring = function (t)
return "Class: Transmission"
end
})
function Transmission.create(toForce, data)
if toForce and not data then
error("Insufficient arguments", 2)
end
local self = setmetatable({}, TransmissionMT)
rawset(self, "skipped", false)
rawset(self, "paused", false)
self.toForce = CreateForce()
self.OriginalTargetForce = CreateForce()
rawset(self, t, NewTimer(self))
rawset(self, "actual_line", 0)
rawset(self, "actual_action", 0)
rawset(self, "actual_step", 0)
rawset(self, "ended", false)
self.Steps = {}
self.Lines = {}
self.Actions = {}
if toForce and data then
if not IsForceEmpty(toForce) then
ForForce(toForce, function ()
local p = GetEnumPlayer()
self.toPlayer = p
ForceAddPlayer(self.toForce, p)
ForceAddPlayer(self.OriginalTargetForce, p)
table.insert(AllInstances[p], self)
end)
end
self.Data = data
end
return self
end
-- To add a player or force to the target force just use ForceAddPlayer(this.toForce, <your player>) or the added ForceAddForce(this.toForce, <your force>)
local oldinit = InitBlizzard
function InitBlizzard()
local t = CreateTrigger()
for i = 0, PLAYER_NEUTRAL_AGGRESSIVE do
What_Force[i] = GetForceOfPlayer(Player(i)) -- To use it if you wanna send the transmission just for 1 player
TriggerRegisterPlayerEvent(t, Player(i), EVENT_PLAYER_END_CINEMATIC)
end
-- If a player skips cinematic he will be removed from every instance trasnmission where is in
TriggerAddAction(t, function ()
local p = GetTriggerPlayer()
for _, self in ipairs(AllInstances[p]) do
if IsPlayerInForce(p, self.toForce) then
ForceRemovePlayer(self.toForce, p)
if p == LocalPlayer then
-- I don't know if this is free of desync (I checked and there is not desync yet)
EndCinematicScene()
if rawget(self, "played") then
StopSound(rawget(self, "played"), false, true)
end
end
end
if IsForceEmpty(self.toForce) then
PauseTimer(rawget(self, "t"))
TimerStart(rawget(self, "t"), RMinBJ(bj_TRANSMISSION_PORT_HANGTIME, TimerGetRemaining(rawget(self, "t"))), false, callback)
end
end
AllInstances[p] = {}
end)
-- --
LocalPlayer = GetLocalPlayer()
ForceCinematicSubtitles(true)
-- --
oldinit()
end
end