I've added support for spell data transfer, thus updating version name to 23.07.2023/13, so mod will ensure all players within game have this addition.
Malekitsu wrote: ↑03 Oct 2023, 00:55
so far the code was all in scripts/general, but:
Code: Select all
Multiplayer.allow_remote_event("MAWMapvarArrived")
Will return error unless it's inside something like events.GameInitialized2.
Shall I change folder to do such online stuff?
It should be inside events.MultiplayerInitialized(), before this event fired, "Multiplayer.allow_remote_event" simply does not exist.
Heal spell logic with today's change could look lite this:
Code: Select all
function events.PlayerCastSpell(t)
if Multiplayer and t.SpellId == 68 and t.TargetKind == 3 and t.Mastery > 0 then
--return if target is not an online teammate
if not table.find(Multiplayer.client_monsters(),t.TargetId) then
return
end
--healing calculation
local persBonus= t.Player:GetPersonality()/1000
local intBonus=t.Player:GetIntellect()/1000
local statBonus=math.max(persBonus,intBonus)
local crit=t.Player:GetLuck()/1500+0.05
local baseHeal=(5+(t.Mastery+1)*t.Skill)
local extraHeal=baseHeal*statBonus
roll=math.random()
local gotCrit=false
if roll<crit then
extraHeal=(extraHeal+baseHeal)*(1.5+statBonus*3/2)-baseHeal
gotCrit=true
end
if gotCrit then
Sleep(1)
Game.ShowStatusText(string.format("You Heal for " .. math.round(baseHeal+extraHeal) .. " Hit points(crit)"))
else
Sleep(1)
Game.ShowStatusText(string.format("You Heal for " .. math.round(baseHeal+extraHeal) .. " Hit points"))
end
--end of healing calculation
t.MultiplayerData[1]=math.round(extraHeal)
t.MultiplayerData[2]=gotCrit
t.MultiplayerData[3]="" -- name will be generated on remote side
t.MultiplayerData[4]=math.round(baseHeal+extraHeal)
t.MultiplayerData[5]=true
end
if Multiplayer and t.SpellId == 68 and t.TargetKind == 4 and t.RemoteData then
local healData = t.RemoteData
local name = Multiplayer.client_name(t.RemoteData.client_id)
Party[t.TargetId].HP=Party[t.TargetId].HP+healData[1]
if Party.High==0 then
Sleep(1)
Game.ShowStatusText(string.format(name .. " critical heals you for " .. healData[4] .. " hit points"))
elseif healData[2] then
Sleep(1)
Game.ShowStatusText(string.format(name .. " critical heals " .. Party[t.TargetId].Name .. " for " .. healData[4] .. " hit points"))
else
Sleep(1)
Game.ShowStatusText(string.format(name .. " heals " .. Party[t.TargetId].Name .. " for " .. healData[4] .. " hit points"))
end
healData[1]=false
end
end
PlayerCastSpell now have tow additional fields in it's data:
t.MultiplayerData - empty table, whatever you put in it will be transferred to remote player targeted by this spell.
t.RemoteData - table with content arrived from caster, it has one predefined field - "client_id" - mulriplayer id of player, who casted the spell.
t.MultiplayerData and t.RemoteData will be nil, if spell does not dupport data transfer.
This approach is supported for limited range of spells - only for buffs, because offensive spells do not trigger PlayerCastSpell event, and some buffs also handled in special way. Supported spells:
Code: Select all
3 FireResistance
5 Haste
8 Immolation
12 WizardEye
13 FeatherFall
14 AirResistance
17 Shield
19 Invisibility
23 Awaken
25 WaterResistance
31 TownPortal
36 EarthResistance
38 StoneSkin
40 StoneToFlesh
45 DetectLife
46 Bless
47 Fate
49 RemoveCurse
50 Preservation
51 Heroism
53 RaiseDead
55 Resurrection
57 RemoveFear
58 MindResistance
61 CureParalysis
64 CureInsanity
67 CureWeakness
68 Heal
69 BodyResistance
71 Regeneration
72 CurePoison
73 Hammerhands
74 CureDisease
75 ProtectionFromMagic
77 PowerCure
83 DayOfTheGods
85 DayOfProtection
86 HourOfPower
88 DivineIntervention
89 Reanimate
95 PainReflection
98 Armageddon
101 TravelersBoon
If you ever need option to send some data directly to specific player, you'll have to setup your own packet, readme has detailed example, here is brief one (script to be used in "General" folder):
Code: Select all
-- Play sound, whenever remote player selected as any spell target
local packets
function events.MultiplayerInitialized()
packets = {
play_sound = {
bulb = function(sound_id)
return Multiplayer.utils.item_to_bin(sound_id)
end,
handler = function(bin_string, metadata)
local sound_id = Multiplayer.utils.binstr_to_item(bin_string)
Game.PlaySound(sound_id)
end,
same_map_only = true,
check_delivery = true,
compress = false
}
}
Multiplayer.utils.init_packets(packets)
end
function events.PlayerCastSpell(t)
if t.TargetKind == 3 then
local client_id = Multiplayer.posessed_by_player(t.TargetId)
if client_id then
Multiplayer.add_to_send_queue(client_id, packets.play_sound:prep(130)) -- 130 - is luteguitar sound id
end
end
end
Malekitsu wrote:
Will come back with more news, unfortunately testing stuff multiplayer is really hard(don't have a 2nd pc).
I've modified GOG executable file a bit, to allow to boot the game, despite one window is already open, but you'll need separate game folder for every copy, otherwise it will cause data access conflicts. Thus you can boot two windows of the game, and connect them to each other using LAN connection mode (if you've manually specified multiplayer port, it should be different in both windows):
https://drive.google.com/file/d/1HOLV8s ... sp=sharing