taken from my scrapped (but oh so loved) RPG. Hasnt been extremely stress tested but it worked when i was alpha testing other systems
uses Table and a modified HeroImage library
JASS:
library PartyLib
globals
endglobals
private module init
private static method onInit takes nothing returns nothing
local integer i = 0
loop
exitwhen i == 10
set p_curPlayer[i] = Party.create().add(Player(i))
set p_perPlayer[i] = p_curPlayer[i]
set i = i + 1
endloop
endmethod
endmodule
private module init2
private static method onInit takes nothing returns nothing
local integer i = 0
local trigger t = CreateTrigger()
local trigger t2 = CreateTrigger()
call no0()
loop
exitwhen i == 10
call TriggerRegisterPlayerChatEvent(t, Player(i), "#", false)
call TriggerRegisterPlayerEvent(t2, Player(i), EVENT_PLAYER_LEAVE)
set i = i + 1
endloop
call TriggerAddCondition(t, Filter(function thistype.onChat))
call TriggerAddCondition(t2, Filter(function thistype.onPlayerLeave))
set t2 = null
set t = null
endmethod
endmodule
struct Party extends array
implement Alloc
private static thistype array p_curPlayer
private static thistype array p_perPlayer
force playerPool
player captain
Table heroImages
Table quests
integer questsCount
Table pings
integer pingsCount
integer heroImagesCount
public static method getParty takes player p returns thistype
return p_perPlayer[GetPlayerId(p)]
endmethod
public method getForce takes nothing returns force
return playerPool
endmethod
public static method isJoinableParty takes player p returns boolean
return integer(p_perPlayer[GetPlayerId(p)]) > 9
endmethod
private method addImage takes player p returns nothing
local integer i = heroImagesCount - 1
loop
exitwhen i < 0
call HeroImage(heroImages[i]).addPlayer(p)
set i = i - 1
endloop
set heroImages[heroImagesCount] = HeroImage.create(udg_PlayerUnit[GetPlayerId(p)+1],playerPool)
set heroImagesCount = heroImagesCount + 1
endmethod
private method removeImage takes player p returns nothing
local integer i = heroImagesCount - 1
loop
exitwhen i < 0
if HeroImage(heroImages[i]).isOwner(p) then
call HeroImage(heroImages[i]).destroy()
set heroImagesCount = heroImagesCount - 1
set heroImages[i] = heroImages[heroImagesCount]
else
call HeroImage(heroImages[i]).destroy()
endif
set i = i - 1
endloop
endmethod
public method startQuest takes integer questThis returns nothing
set quests[questsCount] = questThis
set questsCount = questsCount + 1
endmethod
public method getLevelReq takes nothing returns integer
local integer i = 0
local integer min = 99999999
loop
exitwhen i >= 10
if IsPlayerInForce(Player(i), playerPool) and GetHeroLevel(udg_PlayerUnit[i+1]) < min then
set min = GetHeroLevel(udg_PlayerUnit[i+1])
endif
set i = i + 1
endloop
return min
endmethod
public method addPing takes real x, real y returns nothing
set pings.real[pingsCount*2] = x
set pings.real[pingsCount*2+1] = y
set pingsCount = pingsCount + 1
endmethod
public method removePing takes real x, real y returns nothing
local integer i = 0
loop
exitwhen i >= pingsCount
if pings.real[i*2] == x and pings.real[i*2+1] == y then
set pings.real[i*2] = pings.real[pingsCount*2]
set pings.real[i*2+1] = pings.real[pingsCount*2+1]
return
endif
set i = i + 1
endloop
endmethod
public method finishQuest takes integer questThis returns nothing
local integer i = 0
loop
exitwhen i == questsCount
if quests[i] == questThis then
if i != questsCount - 1 then
set quests[i] = quests[questsCount - 1]
endif
set questsCount = questsCount - 1
return
endif
set i = i + 1
endloop
endmethod
public method getQuests takes nothing returns Table
return quests
endmethod
public static method isPlayerCaptain takes player p returns boolean
return p_perPlayer[GetPlayerId(p)].captain == p
endmethod
public method doesContainPlayer takes player p returns boolean
return IsPlayerInForce(p, playerPool)
endmethod
public method isJoinable takes nothing returns boolean
return integer(this) > 10
endmethod
public method isCaptain takes player p returns boolean
return captain == p
endmethod
public method populateForce takes force f returns nothing
local integer i = 0
loop
exitwhen i == 14
if IsPlayerInForce(Player(i), playerPool) then
call ForceAddPlayer(f,Player(i))
endif
set i = i + 1
endloop
endmethod
public method add takes player p returns thistype
local integer i = 0
if integer(p_perPlayer[GetPlayerId(p)]) > 10 then
call TimedText(p,30,"|cff33ff33Party|r : Player " + I2S(GetPlayerId(p)+1) + " cannot join another party because he/she is already in a party")
return p_perPlayer[GetPlayerId(p)]
endif
if integer(this) <= 10 then
call BJDebugMsg("FATAL ERROR : Attempted to add a player to a default party. Report to [email][email protected][/email]")
return -1
endif
set p_perPlayer[GetPlayerId(p)] = this
if captain != p then
call TimedTextForce(playerPool,30,"|cff33ff33Party|r : " + GetPlayerNameColored(p) + " has joined the party")
set i = questsCount - 1
loop
exitwhen i < 0
call QuestInstance(quests[i]).notifyClosure()
set i = i - 1
endloop
endif
call ForceAddPlayer(playerPool,p)
call addImage(p)
return this
endmethod
public static method create takes nothing returns thistype
local thistype this = thistype.allocate()
set playerPool = CreateForce()
set heroImages = Table.create()
set heroImagesCount = 0
return this
endmethod
public static method onPartyExit takes player p returns nothing
local thistype this = p_perPlayer[GetPlayerId(p)]
if integer(this) < 11 then
call TimedText(p,30,"|cff33ff33Party|r : You aren't in a party")
return
endif
if p == captain then
call TimedText(p,30,"|cff33ff33Party|r : You are the captain of the party, you cannot exit it. Either use \"#transfer {color}\" to transfer ownership or \"#disband\" to break the party")
return
endif
call removeImage(p)
call ForceRemovePlayer(playerPool,p)
set p_perPlayer[GetPlayerId(p)] = p_curPlayer[GetPlayerId(p)]
endmethod
public static method onPartyDisband takes player trig returns nothing
local thistype this = p_perPlayer[GetPlayerId(trig)]
local integer i
//local player p
if integer(this) < 11 then
call TimedText(trig,30,"|cff33ff33Party|r : You aren't in a party")
return
endif
if trig != captain then
call TimedText(trig,30,"|cff33ff33Party|r : You aren't the owner of the party")
return
endif
set i = 0
loop
exitwhen i == heroImagesCount
call HeroImage(heroImages[i]).destroy()
set i = i + 1
endloop
set i = 0
loop
exitwhen i == questsCount
call QuestInstance(quests[i]).notifyClosure()
set i = i + 1
endloop
set i = 0
call TimedTextForce(playerPool,30,"|cff33ff33Party|r : The party has disbanded|r")
loop
exitwhen i == 10
if IsPlayerInForce(Player(i), playerPool) then
set p_perPlayer[i] = p_curPlayer[i]
endif
set i = i + 1
endloop
call DestroyForce(playerPool)
set captain = null
call quests.destroy()
call heroImages.destroy()
call pings.destroy()
call deallocate()
endmethod
public static method onRepick takes player p returns nothing
local thistype this = p_perPlayer[GetPlayerId(p)]
if this <= 10 then
return
endif
if captain == p then
call onPartyDisband(p)
else
call onPartyExit(p)
endif
endmethod
public static method transferOwnership takes player owner, player toplayer returns nothing
local thistype this = p_perPlayer[GetPlayerId(owner)]
if integer(this) < 11 then
call TimedText(owner,30,"|cff33ff33Party|r : You aren't in a party")
return
endif
if owner != captain then
call TimedText(owner,30,"|cff33ff33Party|r : You aren't the owner of the party")
return
endif
if not IsPlayerInForce(toplayer, playerPool) then
call TimedText(owner,30,"|cff33ff33Party|r : " + GetPlayerNameColored(toplayer) + " isn't in the party")
return
endif
set captain = toplayer
endmethod
public static method onPartyForm takes player p returns thistype
local thistype this
if integer(p_perPlayer[GetPlayerId(p)]) > 10 then
call TimedText(p,30,"|cff33ff33Party|r : You are already in a party and cannot form one. Type \"#exit\" than \"#form\" to form your own party")
return -1
endif
set this = thistype.allocate()
set playerPool = CreateForce()
set heroImages = Table.create()
set heroImagesCount = 0
set quests = Table.create()
set questsCount = 0
set captain = p
call add(p)
set p_perPlayer[GetPlayerId(p)] = this
call TimedText(p,30,"|cff33ff33Party|r : You have successfully formed a party. Have other players type #join {your color} to join your party")
return this
endmethod
public static method onExpire takes nothing returns nothing
local thistype this = TimerDetach(GetExpiredTimer())
call DestroyTimer(GetExpiredTimer())
endmethod
public method requestInvite takes player p returns nothing
endmethod
implement init
endstruct
struct PartyInvitationRequest extends array
implement Alloc
static trigger t_onCha
static boolean array awaitingResponse
static thistype array responses
player c
player a
Party t
public method destroy takes nothing returns nothing
set responses[GetPlayerId(a) + (100 * GetPlayerId(c))] = 0
set c = null
set a = null
set t = 0
call deallocate()
endmethod
public static method create takes player awaiting, Party target returns thistype
local thistype this = thistype.allocate()
set responses[GetPlayerId(awaiting) + (100 * GetPlayerId(target.captain))] = this
set c = target.captain
set a = awaiting
set t = target
call TimedText(c,30,"|cff33ff33Party|r : " + GetPlayerNameColored(a) + " requests entrance to your party. \n type \"#accept {color}\" to allow him or \"#reject {color}\" to block his requests for 5 minutes")
return this
endmethod
private static method no0 takes nothing returns nothing
call thistype.allocate()
endmethod
public static method onPlayerLeave takes nothing returns boolean
local Party p = Party.getParty(GetTriggerPlayer())
if Party.isJoinableParty(GetTriggerPlayer()) then
if p.isCaptain(GetTriggerPlayer()) then
call Party.onPartyDisband(GetTriggerPlayer())
else
call Party.onPartyExit(GetTriggerPlayer())
endif
endif
return false
endmethod
public static method onChat takes nothing returns boolean
local thistype this
local string msg = GetEventPlayerChatString()
set msg = StringCase(msg,false)
if SubString(msg,0,1) != "#" then
return false
endif
if SubString(msg, 0, 7) == "#accept" and StringLength(msg) > 9 then
set this = responses[100*GetPlayerId(GetTriggerPlayer()) + color2Number(SubString(msg,8,StringLength(msg)))]
if this == 0 then
call TimedText(GetTriggerPlayer(), 30, "|cff33ff33Party|r : That player does not have a pending request to join your party")
return false
endif
if integer(Party.getParty(Player(color2Number(SubString(msg,8,StringLength(msg)))))) > 10 then
call TimedText(GetTriggerPlayer(),30,"|cff33ff33Party|r : That player has joined another party since the request has been sent")
call destroy()
return false
endif
call DisplayTimedTextToPlayer(a,0,0,30,"|cff33ff33Party|r : You have joined " + GetPlayerNameColored(c) + "'s party")
call t.add(a)
call destroy()
elseif SubString(msg,0,7) == "#reject" and StringLength(msg) > 10 then
set this = responses[100*GetPlayerId(GetTriggerPlayer()) + color2Number(SubString(msg,8,StringLength(msg)))]
if this == 0 then
call TimedText(GetTriggerPlayer(), 30, "|cff33ff33Party|r : That player does not have a pending request to join your party")
return false
endif
if integer(Party.getParty(Player(color2Number(SubString(msg,8,StringLength(msg)))))) > 10 then
call TimedText(GetTriggerPlayer(),30,"|cff33ff33Party|r : That player has joined another party since the request has been sent")
call destroy()
return false
endif
call DisplayTimedTextToPlayer(a,0,0,30,"|cff33ff33Party|r : You have been rejected from your party request.")
call destroy()
elseif SubString(msg,0,5) == "#join" and StringLength(msg) > 7 then
if integer(Party.getParty(GetTriggerPlayer())) > 10 then
call TimedText(GetTriggerPlayer(),30,"|cff33ff33Party|r : You are currently in a party and cannot join another. Type \"#exit\" to leave your party")
return false
endif
if GetPlayerId(GetTriggerPlayer()) == color2Number(SubString(msg,6,StringLength(msg))) then
call TimedText(GetTriggerPlayer(),30,"|cff33ff33Party|r : You cannot join your own party")
return false
endif
if integer(Party.getParty(Player(color2Number(SubString(msg,6,StringLength(msg)))))) < 10 then
call TimedText(GetTriggerPlayer(),30,"|cff33ff33Party|r : That player is currently not in a party")
return false
endif
call TimedText(GetTriggerPlayer(),30,"|cff33ff33Party|r : You have requested to join " + GetPlayerNameColored(Player(color2Number(SubString(msg,6,StringLength(msg))))) + "'s party")
call create(GetTriggerPlayer(),Party.getParty(Player(color2Number(SubString(msg,6,StringLength(msg))))))
elseif SubString(msg,0,5) == "#form" then
call Party.onPartyForm(GetTriggerPlayer())
elseif SubString(msg,0,5) == "#exit" then
call Party.onPartyExit(GetTriggerPlayer())
elseif SubString(msg,0,8) == "#disband" then
call Party.onPartyDisband(GetTriggerPlayer())
endif
return false
endmethod
implement init2
endstruct
endlibrary
uses Table and a modified HeroImage library
JASS:
library HeroImage initializer onInit
struct HeroImage extends array
implement Alloc
static Table originals
static Table copies
static HeroImage array images
static integer imagesCount
Table copyUnits
integer copiesCount
integer unitType
unit original
integer spot
private method storeCopy takes integer u returns nothing
set copies[u] = this
endmethod
private method storeOriginal takes integer u returns nothing
set originals[u] = this
endmethod
private static method retrieveCopy takes integer u returns thistype
return copies[u]
endmethod
private static method retrieveOriginal takes integer u returns thistype
return originals[u]
endmethod
private static method isOriginal takes integer u returns boolean
return originals.has(u)
endmethod
private static method isCopy takes integer u returns boolean
return copies.has(u)
endmethod
private static method removeOriginal takes integer u returns nothing
call originals.remove(u)
endmethod
private static method removeCopy takes integer u returns nothing
call copies.remove(u)
endmethod
public static method onOrder takes nothing returns boolean
local thistype this
if ( not isCopy(GetHandleId(GetOrderTargetUnit()))) then
return false
endif
set this = retrieveCopy(GetHandleId(GetOrderTargetUnit()))
call IssueTargetOrderById(GetTriggerUnit(), GetIssuedOrderId(), this.original)
return false
endmethod
public static method onSelection takes nothing returns boolean
local thistype this
if ( not isCopy(GetHandleId(GetTriggerUnit()))) then
return false
endif
set this = retrieveCopy(GetHandleId(GetTriggerUnit()))
if ( GetLocalPlayer() == GetTriggerPlayer() ) then
call ClearSelection()
call SelectUnit(this.original, true)
call SetCameraPosition(GetUnitX(this.original), GetUnitY(this.original))
endif
return false
endmethod
private static method periodic takes nothing returns nothing
local thistype this
local real originalHp
local real originalMp
local real hp
local real mp
local real maxHp
local unit copy
local integer n = 0
local integer i = 0
loop
exitwhen i == imagesCount
if this.original == null then
call this.destroy()
else
set hp = GetWidgetLife(this.original)
set maxHp = GetUnitState(original, UNIT_STATE_MAX_LIFE)
set originalHp = hp / maxHp
set originalMp = GetUnitState(this.original, UNIT_STATE_MANA) / GetUnitState(original, UNIT_STATE_MAX_MANA)
set n = 0
loop
exitwhen this.copyUnits.unit[n] == null
set copy = this.copyUnits.unit[n]
// HP
if (hp <= 0.405) then
call SetWidgetLife(copy, 1)
else
call SetWidgetLife(copy, GetUnitState(copy, UNIT_STATE_MAX_LIFE) * originalHp)
endif
call SetUnitState(copy, UNIT_STATE_MANA, GetUnitState(copy, UNIT_STATE_MAX_MANA) * originalMp)
set n = n + 1
endloop
endif
set i = i + 1
set this = images[i]
endloop
set copy = null
endmethod
public method addPlayer takes player p returns nothing
local unit u = CreateUnit(p, unitType, WorldBounds.maxX, WorldBounds.maxY, 0)
call storeCopy(GetHandleId(u))
call PauseUnit(u, true)
set copyUnits.unit[copiesCount] = u
set copiesCount = copiesCount + 1
endmethod
public method removePlayer takes player p returns nothing
local integer i = copiesCount - 1
loop
exitwhen i < 0
if GetOwningPlayer(copyUnits.unit[i]) == p then
call removeCopy(GetHandleId(copyUnits.unit[i]))
call RemoveUnit(copyUnits.unit[i])
set copiesCount = copiesCount - 1
set copyUnits.unit[i] = copyUnits.unit[copiesCount]
call copyUnits.remove(copiesCount)
return
endif
set i = i - 1
endloop
call print("error no remove player")
endmethod
public method destroy takes nothing returns nothing
local integer i = copiesCount - 1
loop
exitwhen i < 0
call removeCopy(GetHandleId(copyUnits.unit[i]))
call RemoveUnit(copyUnits.unit[i])
call copyUnits.remove(i)
set i = i - 1
endloop
call removeOriginal(GetHandleId(original))
//call RemoveUnit(original)
set imagesCount = imagesCount - 1
set images[spot] = images[imagesCount]
set images[imagesCount] = 0
endmethod
public method isOwner takes player p returns boolean
return GetOwningPlayer(original) == p
endmethod
public static method create takes unit orig, force players returns thistype
local thistype this
local integer id = GetHandleId(orig)
local integer playa = GetPlayerId(GetOwningPlayer(orig))
local integer i = 0
local player p
local unit u
if isOriginal(id) then
call print("Error : "+I2S(id)+" already has a copy")
elseif isCopy(id) then
call print("Error : "+I2S(id)+" is a copy")
endif
set this = thistype.allocate()
set original = orig
set copyUnits = Table.create()
set copiesCount = 0
set unitType = GetUnitTypeId(orig)
call storeOriginal(id)
set spot = imagesCount
set images[spot] = this
set imagesCount = imagesCount + 1
loop
exitwhen i >= 11
set p = Player(i)
if i != playa and IsPlayerInForce(p, players) then
set u = CreateUnit(p, unitType, WorldBounds.maxX, WorldBounds.maxY, 0)
call storeCopy(GetHandleId(u))
call PauseUnit(u, true)
set copyUnits.unit[copiesCount] = u
set copiesCount = copiesCount + 1
endif
set i = i + 1
endloop
set p = null
set u = null
return this
endmethod
endstruct
private function onInit takes nothing returns nothing
local trigger onSelect = CreateTrigger()
local trigger onOrder = CreateTrigger()
local integer i = 0
call TriggerAddCondition(onSelect, Filter(function HeroImage.onSelection))
call TriggerAddCondition(onOrder, Filter(function HeroImage.onOrder))
loop
exitwhen i >= 11
call TriggerRegisterPlayerUnitEvent(onOrder, Player(i), EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER, null)
call TriggerRegisterPlayerUnitEvent(onSelect, Player(i), EVENT_PLAYER_UNIT_SELECTED, null)
set i = i + 1
endloop
set HeroImage.originals = Table.create()
set HeroImage.copies = Table.create()
set HeroImage.imagesCount = 0
endfunction
endlibrary