HeroEngine Forums
Welcome, Guest. Please login or Register for HeroCloud Account.

Author Topic: Goups - basic  (Read 2238 times)

Thazager

  • General Accounts
  • *
  • Posts: 1160
  • Never stop learning
    • View Profile
Goups - basic
« on: Feb 03, 16, 11:46:01 PM »

Advanced tutorial (lots of parts)

part1

This will allow players to group with other players. You can set the max amount for a group (in code). A player can invite another by right clicking on the target panel. It checks to see if the player can join. All players are able to quit the group, the leader has extra options - kick, promote, and search (which can be found in another tutorial). In function getGroupMax() you can set the max in group.

*There will be a few linked scripts by calls, so each script might be compiled/submitted a few times.
__________________________________________________________________
From the basic window tutorial
Make basic window here. This is a base window and will be used in many of my Tutorials. It uses the GUI pics from textures that all engines have. This can be skipped if you have the basic window already from another tutorial.

Make basic button here. This will also be used in many of my tutorials.

Add manaBar to GUIs here This will be used in some other tutorials also.

__________________________________________________________________
In (client side) script MiscUtils

if you don't have this yet, add function

Code: [Select]
// var char = MiscUtils:getCharPointer()
public function getCharPointer() as NodeRef of Class E_playerCharacter
  acct as NodeRef of Class E_playerAccount = GetAccountID()
  if acct <> None
    char as NodeRef of Class E_playerCharacter = acct.GetMyCharacter()
    return char
  .
  return None
.
__________________________________________________________________

First is a script that does not have a class. It is linked through calls to its functions. Compile and submit.

In new (client side) script TMP_GroupMesgs

Code: [Select]
//=============================================================================================================
// messages to send to player
//=============================================================================================================
// join
public function JoinGroupMesg(JoinName as String)
  $CHAT.getChatWindow().AddChatMessage(JoinName+" has joined the group.", "Game")
.

// player joins group - feedback
remote function GroupJoin()
  $CHAT.getChatWindow().AddChatMessage("You have joined the group.", "Game")
.

public function FullGroupMesg(JoinName as String)
  $CHAT.getChatWindow().AddChatMessage("The group is now full, "+JoinName+" can not join.", "Game")
.

// leader------------------------------------------------------------
public function NotLeaderMesg()
  $CHAT.getChatWindow().AddChatMessage("You are not leader of the group.", "Game")
.

public function PromoteLeaderMesg(name as String)
  $CHAT.getChatWindow().AddChatMessage("You made "+name+" Group Leader.", "Game")
.

public function YouLeaderMesg()
  $CHAT.getChatWindow().AddChatMessage("You are already Group Leader.", "Game")
.

public function NewLeaderMesg(msg as String)
  $CHAT.getChatWindow().AddChatMessage(msg+" now Group Leader.", "Game")
.

// leaving group-----------------------------------------------------
public function LeaveGroupMesg()
  $CHAT.getChatWindow().AddChatMessage("You have left the group.", "Game")
.

// no player targeted------------------------------------------------
public function NoPlayerMesg()
  $CHAT.getChatWindow().AddChatMessage("No player is targeted.", "Game")
.

// invite checks-----------------------------------------------------
public function InvitePlayerMesg(JoinName as String)
  $CHAT.getChatWindow().AddChatMessage("Sending group invite to "+ JoinName, "Game")
.

public function SelfInviteMesg()
  if TMP_GroupWindowClassMethods:getGroupAmount() < 2
    $CHAT.getChatWindow().AddChatMessage("You can not invite yourself to a group.", "Game")
  else
    $CHAT.getChatWindow().AddChatMessage("You are already in this group.", "Game")
  .
.

public function PlayerInOurGroupMesg(JoinName as String)
  $CHAT.getChatWindow().AddChatMessage(JoinName +" is already in our group.", "Game")
.

public function PlayerInOtherGroupMesg(JoinName as String)
  $CHAT.getChatWindow().AddChatMessage(JoinName +" is already in a group.", "Game")
.

public function NPCTargetMesg(name as String)
  $CHAT.getChatWindow().AddChatMessage("You cant invite "+name+" to the group.", "Game")
.

// kicked------------------------------------------------------------
public function KickPlayerMesg(name as String)
  $CHAT.getChatWindow().AddChatMessage("You removed "+name+" from group.", "Game")
.

public function KickGroupMesg(name as String)
  $CHAT.getChatWindow().AddChatMessage(name+" was removed from the group.", "Game")
.

public function GotKickedMesg()
  $CHAT.getChatWindow().AddChatMessage("You were removed from the group.", "Game")
.

public function NoKickSelfMesg()
  $CHAT.getChatWindow().AddChatMessage("You cant kick yourself from group, use Quit Group.", "Game")
.

// no group----------------------------------------------------------
public function NotInGroupMesg()
  $CHAT.getChatWindow().AddChatMessage("You are not in a group.", "Game")
.
__________________________________________________________________

In the DOM, create a new (client side) field
name = tmp_groupPlayers
type = list of string

create a new (client side) field
name = tmp_groupMe
type = string

In the DOM (client side) class E_PlayerCharacter
add a field (above) tmp_groupPlayers
add a field (above) tmp_groupMe

create a new (client side) field
name = tmp_target
type = id

In the DOM (client side) class E_targetStatusBar
add a field (above) tmp_target
__________________________________________________________________

In the DOM, create a new (server side) field
name = tmp_groupPlayers
type = list of string

create a new (server side) field
name = tmp_groupMe
type = string

In the DOM (server side) class E_PlayerCharacter
add a field (above) tmp_groupPlayers
add a field (above) tmp_groupMe

__________________________________________________________________
In (client side) script E_ChatHandlerClassMethods

Code: [Select]
// get mesg from server, send to player
remote method sendTell( message as String, channel as String )
  $CHAT.GetChatWindow().AddChatMessage( message, channel )
.
__________________________________________________________________
In the DOM, create a new (client side) field
name = tmp_groupNum
type = integer

In the DOM, create a new (client side) class
name = TMP_GroupWindow
archtype = guicontrol

add a parent to the class, TMP_Window
add a field (above) tmp_groupNum
add a field myTimer

click open script

In new (client side) script TMP_GroupWindow
// get code from next post (below) part2

*compile and submit script
__________________________________________________________________
In the DOM, create a new (client side) field
name = tmp_InviteSender
type = string

In the DOM, create a new (client side) class
name = TMP_InviteWindow
archtype = guicontrol

add a parent to the class, TMP_Window
add a field (above) tmp_InviteSender

click open script

In new (client side) script TMP_InviteWindow
// get code from next post (below) part3

*compile and submit script
__________________________________________________________________
In the DOM, create a new (server side) class
name = TMP_Groups
archtype = data

click open script

In new (server side) script TMP_Groups
// get code from next post (below) part3

*compile and submit script
__________________________________________________________________
*Now,

In new (client side) script TMP_GroupWindow
remove "///**" from the calls to server, then compile and submit script

In new (client side) script TMP_InviteWindow
also remove "///**" from the calls to server, then compile and submit script

This should link all scripts.
__________________________________________________________________
In new (XML) script TMP_StatusBar

Code: [Select]
<createControlType inheritFrom='_panel' class='TMP_StatusBar' type='TMP_StatusBar' description='' treePath='CleanEngine' name="TMP_StatusBar">
  <size x="166" y="40"/>
  <defaultStatePresentation>
    <color a="0"/>
  </defaultStatePresentation>
  <_label name="nameLabel" dockMode="TOP" text="name" displayfont="JUMBO" dropShadowAlpha="1" justification="BOTTOMLEFT">
    <size x="166"/>
    <defaultStatePresentation>
      <color r="1" g="1" b="1"/>
    </defaultStatePresentation>
    <autoCenter horizontal="true"/>
  </_label>
  <_panel name="HealthPanel" dockMode="TOP">
    <size x="166" y="9"/>
    <defaultStatePresentation>
      <color a="0"/>
    </defaultStatePresentation>
    <_panel name="atopLine" dockMode="TOP">
      <size x="166"/>
      <defaultStatePresentation>
        <color r="0" g="0" b="0"/>
      </defaultStatePresentation>
    </_panel>
    <_panel name="BtmLine" dockMode="BOTTOM">
      <size x="166"/>
      <defaultStatePresentation>
        <color r="0" g="0" b="0"/>
      </defaultStatePresentation>
    </_panel>
    <_panel name="HealthSlider" texture="\GUI\ccs_elements_v3.dds">
      <size x="90" y="9"/>
      <defaultStatePresentation>
        <color r="0" b="0"/>
        <position x="40" y="206"/>
        <size x="32" y="32"/>
      </defaultStatePresentation>
      <hoverStatePresentation>
        <color r="0" b="0"/>
        <position x="40" y="206"/>
        <size x="32" y="32"/>
      </hoverStatePresentation>
    </_panel>
    <_label name="text" dockMode="FILL" text="test" displayfont="SMALLTEXT" dropShadowAlpha="1" justification="CENTER">
      <size x="166" y="7"/>
      <defaultStatePresentation>
        <color r="1" g="1" b="1"/>
      </defaultStatePresentation>
    </_label>
    <tmp_button name="Button" texture="">
      <size x="166" y="9"/>
      <defaultStatePresentation>
        <color a="0"/>
      </defaultStatePresentation>
      <hoverStatePresentation>
        <color a="0"/>
      </hoverStatePresentation>
      <set name="TMP_StatusBar.HealthPanel.Button.text">
        <defaultStatePresentation>
          <color g="1" b="1"/>
        </defaultStatePresentation>
        <set name='TMP_StatusBar.HealthPanel.Button.text' attribute='text' value=""/>
        <set name='TMP_StatusBar.HealthPanel.Button.text' attribute='displayfont' value="SMALLTEXT"/>
        <set name='TMP_StatusBar.HealthPanel.Button.text' attribute='dropShadowAlpha' value="1"/>
      </set>
    </tmp_button>
  </_panel>
  <_panel name="ManaPanel" dockMode="BOTTOM">
    <size x="166" y="9"/>
    <defaultStatePresentation>
      <color a="0"/>
    </defaultStatePresentation>
    <_panel name="atopLine" dockMode="TOP">
      <size x="166"/>
      <defaultStatePresentation>
        <color r="0" g="0" b="0"/>
      </defaultStatePresentation>
    </_panel>
    <_panel name="BtmLine" dockMode="BOTTOM">
      <size x="166"/>
      <defaultStatePresentation>
        <color r="0" g="0" b="0"/>
      </defaultStatePresentation>
    </_panel>
    <_panel name="ManaSlider" texture="\GUI\ccs_elements_v3.dds">
      <size x="90" y="9"/>
      <defaultStatePresentation>
        <color r="0" g="0"/>
        <position x="40" y="206"/>
        <size x="32" y="32"/>
      </defaultStatePresentation>
      <hoverStatePresentation>
        <color r="0" g="0"/>
        <position x="40" y="206"/>
        <size x="32" y="32"/>
      </hoverStatePresentation>
    </_panel>
    <_label name="text" dockMode="FILL" ignoreMouseEvents="false" text="test" displayfont="SMALLTEXT" dropShadowAlpha="1" justification="CENTER">
      <size x="166" y="7"/>
      <defaultStatePresentation>
        <color r="1" g="1" b="1"/>
      </defaultStatePresentation>
    </_label>
    <tmp_button name="Button" texture="">
      <size x="166" y="9"/>
      <defaultStatePresentation>
        <color a="0"/>
      </defaultStatePresentation>
      <hoverStatePresentation>
        <color a="0"/>
      </hoverStatePresentation>
      <set name="TMP_StatusBar.ManaPanel.Button.text">
        <defaultStatePresentation>
          <color g="1" b="1"/>
        </defaultStatePresentation>
        <set name='TMP_StatusBar.ManaPanel.Button.text' attribute='text' value=""/>
        <set name='TMP_StatusBar.ManaPanel.Button.text' attribute='displayfont' value="SMALLTEXT"/>
        <set name='TMP_StatusBar.ManaPanel.Button.text' attribute='dropShadowAlpha' value="1"/>
      </set>
    </tmp_button>
  </_panel>
</createControlType>

__________________________________________________________________
In new (XML) script TMP_GroupWindow

Code: [Select]
<createControlType inheritFrom='TMP_Window' class='TMP_GroupWindow' type='TMP_GroupWindow' description='' treePath='' name="TMP_GroupWindow" tmp_groupNum="0">
  <size x="200" y="125"/>
  <set name="TMP_GroupWindow.BGpanel">
    <size x="192" y="117"/>
  </set>
  <_label name="title" text="Group" displayfont="JUMBO" dropShadowAlpha="1" justification="CENTER" insertBefore="Butpanel">
    <size x="60"/>
    <defaultStatePresentation>
      <color r="1" g="1" b="0"/>
    </defaultStatePresentation>
    <autoCenter horizontal="true"/>
  </_label>
  <tmp_button name="quit" insertBefore="Butpanel">
    <position x="140" y="5"/>
    <size x="40"/>
    <set name='TMP_GroupWindow.quit.text' attribute='text' value="Quit"/>
  </tmp_button>
  <_panel name="Butpanel" visible="false" texture="">
    <position x="10" y="98"/>
    <size x="180" y="20"/>
    <anchor top="false"/>
    <defaultStatePresentation>
      <color a="0"/>
      <position y="0"/>
      <size x="1" y="1"/>
    </defaultStatePresentation>
    <autoCenter horizontal="true"/>
    <tmp_button name="kick" insertBefore="promote">
      <size x="40"/>
      <set name='TMP_GroupWindow.Butpanel.kick.text' attribute='text' value="Kick"/>
    </tmp_button>
    <tmp_button name="promote" insertBefore="search">
      <position x="45"/>
      <size x="65"/>
      <set name='TMP_GroupWindow.Butpanel.promote.text' attribute='text' value="Promote"/>
    </tmp_button>
    <tmp_button name="search">
      <position x="120"/>
      <size x="60"/>
      <set name='TMP_GroupWindow.Butpanel.search.text' attribute='text' value="Search"/>
    </tmp_button>
  </_panel>
  <_panel name="clientarea">
    <size x="200" y="102"/>
    <defaultStatePresentation>
      <color a="0"/>
    </defaultStatePresentation>
    <TMP_StatusBar name="member1">
      <position x="17" y="15"/>
      <autoCenter horizontal="true"/>
    </TMP_StatusBar>
    <TMP_StatusBar name="member2">
      <position x="17" y="55"/>
      <autoCenter horizontal="true"/>
    </TMP_StatusBar>
  </_panel>
</createControlType>
__________________________________________________________________
In (client side) script E_targetStatusBarClassMethods

Code: [Select]
// script starts empty

// mouse clicks on target bar
method onMouseClick(args references Class GUIMouseEvent)
  target as NodeRef of Class GUIControl = args.source

  if args.rightButton
    when target.name
      is "targetStatusBar"
        TMP_InviteWindowClassMethods:SendInvite()
      .
    .
  .
.


*compile/submit
This will allow player to right click on target bar to "invite".
__________________________________________________________________
In (client side) script E_TargetCircleClassMethods

In method E_UpdateTargetCircle
under
       statusbar.SetName(realtarget.name)
add:

Code: [Select]
      getTargetInfo(realtarget)  // get info for group

In method E_StopTarget
under
  me.E_TargetingFX = 0
add:

Code: [Select]
  var statusbar = getTargetClass()   // remove targetbar
  if statusbar <> None
    DestroyNode(statusbar)
  .

add functions:

Code: [Select]
// get info for target
function getTargetInfo(target as NodeRef)
  where target is kindof E_playerCharacter
    if checkTargetInGroup()
      TMP_GroupWindowClassMethods:SetGroupTargetPanel(target)
    .
  .
.

// check target in a group
function checkTargetInGroup() as Boolean
  var main = getTargetClass()   // get target noderef
  target as NodeRef = main.tmp_target

  where target is kindof E_playerCharacter
    members as List of String = target.tmp_groupPlayers
    amount as Integer
 
    // check for more than 1 in group
    foreach info in members
      if info <> ""
        amount += 1
      .
    .
    if amount > 1
      return true
    .
  .
  return false
.

function getTargetClass() as NodeRef of Class E_targetStatusBar
  return FindGUIControlByName(None, "game.targetStatusBar")
.


*compile/submit
« Last Edit: Feb 04, 16, 12:39:42 AM by Thazager »
Logged
Lead scripter for EO, Repop helper.
HSL Video tutorials:
https://community.heroengine.com/forums/index.php/topic,1719.msg36858.html#msg3685

Thazager

  • General Accounts
  • *
  • Posts: 1160
  • Never stop learning
    • View Profile
Re: Goups - basic
« Reply #1 on: Feb 03, 16, 11:56:02 PM »

*continued from above (max chars on post 20k)
part2a

In new (client side) script TMP_GroupWindow

Code: [Select]
// init main window
shared function Start()
  var main = getMainWindowClass()
  if main <> None
    DestroyNode( main )
  .
  main = CreateNodeFromPrototype("TMP_GroupWindow")
  main.build = true
  main.position.x = 0
  main.position.y = 200
.

// toggle the window
public function toggleWindow()
  var win = getMainWindowClass()
  if win == None
    ShowGroupWindow()      // build it
  else
    destroynode(win)       // remove it
  .
.

// set max for group
public function getGroupMax() as Integer
  return 4
.

// get amount in group
public function getGroupAmount() as Integer
  var char = MiscUtils:getCharPointer()
  members as List of String = char.tmp_groupPlayers      // temp info gather
  amount as Integer
  foreach val in members
    if val <> ""
      amount += 1
    .
  .
  return amount
.

// check for area change - display of group
function checkInGroup() as Boolean
  var char = MiscUtils:getCharPointer()
  members as List of String = char.tmp_groupPlayers
  amount as Integer

  // check for more than 1 in group
  foreach info in members
    if info <> ""
      amount += 1
    .
  .
  if amount > 1
    return true
  .
  return false
.

// init my group values for list - just me in group
// creates a list when player enters game
// called from server with area info
remote public function InitGroupValues(data as String)
  var char = MiscUtils:getCharPointer()
  char.tmp_groupMe = data
  members as List of String
  members = char.tmp_groupPlayers                 // get current value

  if checkInGroup() = true
    ShowGroupWindow()
///**    call server TMP_GroupsClassMethods:sendGroupDataToGroup(members, "save", "")

  else
    // set player to solo
    clear members
    add back data to members    // player in 1st position
 
    amt as Integer = getGroupMax()
    loop i from 2 to amt        // amount in group
      add back "" to members    // fill with blanks
    .
    char.tmp_groupPlayers = members      //save data
///**    call server TMP_GroupsClassMethods:savePlayerGroupValues(members)
  .
.

// check which button clicked
method _OnButtonMouseClick(button as NodeRef of Class _GUIButton, args references Class GUIMouseEvent)

  if args.leftButton
    when button.name
      is "quit"
        LeaveGroup()
      .
      is "kick"
        kickPlayer()
      .
      is "promote"
        changeLeader()
      .
      is "search"
//        TMP_SocialWindowClassMethods:windowToggle()   // if this tutorial was added
      .
    .
  .
.

// check for player clicked
method onMouseClick(args references Class GUIMouseEvent)
  target as NodeRef of Class GUIControl = args.source

  // works with either left or right click
  if target.name <> "TMP_GroupWindow"
    var group = getGroupPanel(target)
    if group <> None
      clickPlayerPanel(group)
    .
  .
.

//=====================================
// Join / Leave Group
//=====================================
// player joins this group
// called from server  - when player joins
remote function JoinThisGroup(members as List of String)
  saveGroupMemberData(members)
  ShowGroupWindow()
.

// save the member data
// called from server - when getting new data
remote function saveGroupMemberData(members as List of String)
  var char = MiscUtils:getCharPointer()
  char.tmp_groupPlayers = members      //save data
///**  call server TMP_GroupsClassMethods:savePlayerGroupValues(members)
.

//=====================================
// player leaves group
// quit (not kicked)
public function LeaveGroup()
  if checkInGroup() = false
    TMP_GroupMesgs:NotInGroupMesg()
    return
  .
  var char = MiscUtils:getCharPointer()
  members as List of String = char.tmp_groupPlayers
  num as Integer = TMP_GroupWindowClassMethods:findPlayerInGroup(char.name)

  info as String = members[num]          // this player's info
  members[num] = ""

  amt as Integer = getGroupMax()
  loop i from 2 to amt
    if members[i-1] = ""                 // cleared this player?
      members[i-1] = members[i]          // move player up in list
      members[i] = ""                    // clear were they moved from
    .
  .
  char.tmp_groupPlayers = members        // save new list
///**  call server TMP_GroupsClassMethods:sendGroupDataToGroup(members, "quit", "")     // tell others
  TMP_GroupMesgs:LeaveGroupMesg()

  // reset my values for group - empty
  InitGroupValues(info)
  var win = getMainWindowClass()
  if win <> None
    destroynode(win)
  .
.

// player leaves this group
// called from server for leaving player
remote function PlayerLeftGroup(members as List of String, name as String)
  var char = MiscUtils:getCharPointer()
  char.tmp_groupPlayers = members      //save data
///**  call server TMP_GroupsClassMethods:savePlayerGroupValues(members)

  $CHAT.getChatWindow().AddChatMessage(name+" has left the group.", "Game")
  ShowGroupWindow()
.

// find the player by name in group
function findPlayerInGroup(name as String) as Integer
  var char = MiscUtils:getCharPointer()
  members as List of String = char.tmp_groupPlayers      // temp info gather
  dataList as List of String
  offset as Integer         // which player in group

  amount as Integer
  foreach info in members
    dataList = MiscUtils:getGroupData(info)
    amount += 1
    if name = dataList[5]   // name of player
      offset = amount
      break
    .
  .
  return offset
.

// find the player by offset in group
function getGroupPlayerName(num as Integer) as String
  var char = MiscUtils:getCharPointer()
  members as List of String = char.tmp_groupPlayers      // temp info gather
  dataList as List of String
  info as String
  name as String

  if (num < getGroupAmount() +1) and num > 0
    info = members[num]
    dataList = MiscUtils:getGroupData(info)
    name = dataList[5]
  .
  return name
.

//=====================================
// Kicked
//=====================================
// kick the selected player from group
function kickPlayer()
  if checkPlayerLeading()     // leader only function
    var char = MiscUtils:getCharPointer()
    var main = getMainWindowClass()
    playNum as Integer = main.tmp_groupNum
    name as String = getGroupTargetName(playNum)

    if name = char.name
      TMP_GroupMesgs:NoKickSelfMesg()
    else if name <> ""
      RemovePlayer(playNum)
      TMP_GroupMesgs:KickPlayerMesg(name)
///**      call server TMP_GroupsClassMethods:sendGroupDataToGroup(char.tmp_groupPlayers, "kick", name)    // tell group
    else
      TMP_GroupMesgs:NoPlayerMesg()
    .
  .
.

// remove this player from group
function RemovePlayer(position as Integer)
  var char = MiscUtils:getCharPointer()
  members as List of String = char.tmp_groupPlayers      // members of this group

  info as String = members[position]     // this player's info
  name as String = getGroupPlayerName(position)

  members[position] = ""      // clear player out

  amt as Integer = getGroupMax()
  loop i from 2 to amt
    if members[i-1] = ""                 // empty spot here?
      members[i-1] = members[i]          // move player up in list
      members[i] = ""                    // clear were they moved from
    .
  .
  char.tmp_groupPlayers = members        // save new list
///**  call server TMP_GroupsClassMethods:RemovePlayerFromGroup(name, info)
.

// player kicked from group - feedback
remote function KickGroup(info as String)
  // reset my values for group - empty
  var char = MiscUtils:getCharPointer()
  members as List of String

  add back info to members    // player in 1st position

  amt as Integer = getGroupMax()
  loop i from 2 to amt        // amount in group
    add back "" to members    // fill with blanks
  .
  char.tmp_groupPlayers = members      //save data
///**  call server TMP_GroupsClassMethods:savePlayerGroupValues(members)

  var win = getMainWindowClass()
  if win <> None
    destroynode(win)
  .
  TMP_GroupMesgs:GotKickedMesg()
.

// player kicked from this group
// called from server for group
remote function PlayerKickGroup(members as List of String, name as String)
  var char = MiscUtils:getCharPointer()
  char.tmp_groupPlayers = members      //save data
///**  call server TMP_GroupsClassMethods:savePlayerGroupValues(members)

  TMP_GroupMesgs:KickGroupMesg(name)
  ShowGroupWindow()
.

//=====================================
// new leader
//=====================================
// change leaders to that of target player
function changeLeader()
  if checkPlayerLeading()     // leader only function
    var char = MiscUtils:getCharPointer()
    var main = getMainWindowClass()
    playNum as Integer = main.tmp_groupNum
    name as String = getGroupTargetName(playNum)

    if name = char.name
      TMP_GroupMesgs:YouLeaderMesg()
    else if name <> ""
      SwapLeader(playNum)
      TMP_GroupMesgs:PromoteLeaderMesg(name)
///**      call server TMP_GroupsClassMethods:sendGroupDataToGroup(char.tmp_groupPlayers, "lead", name)    // tell others
    else
      TMP_GroupMesgs:NoPlayerMesg()
    .
  .
.

// swap this player places with group leader
function SwapLeader(position as Integer)
  var char = MiscUtils:getCharPointer()
  members as List of String = char.tmp_groupPlayers      // members of this group

  temp as String = members[1]      // save leader info
  members[1] = members[position]   // move new player to leader spot
  members[position] = temp         // leader now at players old position
  char.tmp_groupPlayers = members  // save new list
.

// change leaders
remote function NewPlayerLeader(members as List of String, name as String)
  var char = MiscUtils:getCharPointer()
  char.tmp_groupPlayers = members      //save data
///**  call server TMP_GroupsClassMethods:savePlayerGroupValues(members)

  msg as String = name+" is"
  if name = char.name     // this player?
    msg = "You are"
  .

  TMP_GroupMesgs:NewLeaderMesg(msg)
  ShowGroupWindow()
.

//=====================================
// pick player
//=====================================
// choose player in group by clickin player panel
function clickPlayerPanel(target as NodeRef of Class TMP_StatusBar)
  playNum as Integer = SubString(target.name,7,1)

  var main = getMainWindowClass()
  if main.tmp_groupNum <> 0
    var old = getGroupPanelName(main.tmp_groupNum)
    old.defaultStatePresentation.color = MiscUtils:MakeRGBA(1,1,1,1) // reset last
  .

  var player = getGroupPanelName(playNum)
  player.defaultStatePresentation.color = MiscUtils:MakeRGBA(1,0,0,1) // set new

  main.tmp_groupNum = playNum                       // save who is selected

  var char = MiscUtils:getCharPointer()
  members as List of String = char.tmp_groupPlayers

  info as String = members[playNum]                 // this players info
  dataList as List of String = MiscUtils:getGroupData(info)

  acctID as ID = dataList[1]    // get acct
  $E_TargetCircle.E_UpdateTargetCircle(acctID)
.

// set target on group panel, when player clicked
public function SetGroupTargetPanel(target as NodeRef of Class E_playerCharacter)
  playNum as Integer = findPlayerInGroup(target.name)

  var main = getMainWindowClass()
  if main.tmp_groupNum <> 0
    var old = getGroupPanelName(main.tmp_groupNum)
    old.defaultStatePresentation.color = MiscUtils:MakeRGBA(1,1,1,1) // reset last
  .

  var player = getGroupPanelName(playNum)
  player.defaultStatePresentation.color = MiscUtils:MakeRGBA(1,0,0,1) // set new

  main.tmp_groupNum = playNum                       // save who is selected
.

// clear all targ names
public function clearGroupTargetPanel()
  var main = getMainWindowClass()
  if main <> None
    if main.tmp_groupNum <> 0
      var old = getGroupPanelName(main.tmp_groupNum)
      old.defaultStatePresentation.color = MiscUtils:MakeRGBA(1,1,1,1) // reset last
    .
    main.tmp_groupNum = 0                       // save none selected
  .
.

//=====================================
// change locations
//=====================================
// called from server
// when player loads into area
remote function ChangeAreas(members as List of String, name as String)
  var char = MiscUtils:getCharPointer()
  char.tmp_groupPlayers = members      //save data

  amt as Integer = getGroupAmount()
  if amt > 1
    // start timer for new value
    var win = getMainWindowClass()
    if( win.myTimer.timerState == ON )
      win.myTimer.stop()
    .
    win.myTimer.fireRate = 00:00:01
    win.myTimer.start()
  .
.

// timer to show updates - group window
method myTimer_tick()
  var win = getMainWindowClass()
  if( win.myTimer.timerState == ON )
    win.myTimer.stop()
  .

  var char = MiscUtils:getCharPointer()
  members as List of String = char.tmp_groupPlayers
  dataList as List of String
  info as String

  // check for all members showing in group
  amt as Integer = getGroupMax()
  loop i from 1 to amt
    info = members[i]             // get current player
    if info <> ""
      dataList = MiscUtils:getGroupData(info)
      if PlayerSameArea(i)
        target as NodeRef = dataList[1]   // get acct number
        if target <> None
          where target is kindof E_playerAccount
            LinkPlayerValues(target, i)
          .
        else
          // start timer to check again
          win.myTimer.fireRate = 00:00:01
          win.myTimer.start()
        .
      else
        greyPlayerPanel(i)
      .
    .
  .
.
« Last Edit: Feb 04, 16, 12:24:16 AM by Thazager »
Logged
Lead scripter for EO, Repop helper.
HSL Video tutorials:
https://community.heroengine.com/forums/index.php/topic,1719.msg36858.html#msg3685

Thazager

  • General Accounts
  • *
  • Posts: 1160
  • Never stop learning
    • View Profile
Re: Goups - basic
« Reply #2 on: Feb 03, 16, 11:57:47 PM »

*continued from above (max chars on post 20k)
part2b

In new (client side) script TMP_GroupWindow continued

Code: [Select]
//=====================================
// Main display
//=====================================
// add player to group window
// display group window based on amount in group
function ShowGroupWindow()
  var char = MiscUtils:getCharPointer()
  members as List of String = char.tmp_groupPlayers
  dataList as List of String
  info as String
  amount as Integer

  Start()                         // make sure window is there
  var client = getClientArea()
  foreach child in client.children  // clear old
    DestroyNode( child )
  .
  amt as Integer = getGroupMax()

  // 5 players in group
  loop i from 1 to amt
    info = members[i]             // get current player
    if info <> ""
      amount += 1
      dataList = MiscUtils:getGroupData(info)  // info of current member
      makePlayerPanel(i)                       // make panel for member

      // link up the HP, mana values
      target as NodeRef = dataList[1]
      if PlayerSameArea(i)
        if target <> None
          where target is kindof E_playerAccount
            LinkPlayerValues(target, i)        // link HP/mana to player
            setGroupLeaderName(i)              // check/set for leader
          .
        .
      else
        greyPlayerPanel(i)                     // playre inn diff area
      .
    .
  .
  if checkPlayerLeading()
    setLeaderButtons()                         // extra buttons for leader
  .

  // check for less than 2 in group
  var main = getMainWindowClass()
  if amount < 2
    DestroyNode( main )
  .
.

// set name of player in group
function setGroupLeaderName(which as Integer)
  var PlayerName = getGroupPanelName(which)
  if which = 1                    // 1st in group is leader
    PlayerName.text += " (Leader)"
  .
.

// get name of target in group
function getGroupTargetName(playNum as Integer) as String
  var player = getGroupPanelName(playNum)
  name as String = player.text
  name = ReplaceString(name, " (Leader)", "")    // remove extra (might be there)
  return name
.

// gather and send player values to panel
function LinkPlayerValues(target as NodeRef of Class E_playerAccount, i as Integer)
  player as NodeRef of Class E_playerCharacter = target.GetMyCharacter()
  if player <> None
    var bar = getGroupCharPanel(i)
    setListeners(player, bar)   // player
  .
.

// check if player in same area - to show
function PlayerSameArea(num as Integer) as Boolean
  var char = MiscUtils:getCharPointer()
  members as List of String = char.tmp_groupPlayers

  info as String = members[num]      // get current player info
  dataList as List of String = MiscUtils:getGroupData(info)
  myData as List of String = MiscUtils:getGroupData(char.tmp_groupMe)

  if dataList[5] <> char.name       // check same player
    if dataList[2] = myData[2]      // same area?
      return true
    .
  else
    return true     // same player - good area
  .
  return false
.

// check if this player is the leader of the group
// good if player is solo
function checkPlayerLeading() as Boolean
  var char = MiscUtils:getCharPointer()
  members as List of String = char.tmp_groupPlayers      // members of this group

  dataList as List of String = MiscUtils:getGroupData(members[1])   // leader's info
  name as String = dataList[5]

  if name = char.name          // this player is leader?
    return true
  .
  return false
.

// make group panel for current player
function makePlayerPanel(num as Integer)
  var main = getMainWindowClass()
  panel as NodeRef of Class GUIPanel = CreateNodeFromPrototype("TMP_StatusBar")
  panel.build = true
  panel.name = "member"+ num
  panel.position.y = panel.size.y * (num-1) + 15
  panel.autoCenter.horizontal = true
  main.size.y = panel.size.y * num + 22

  // set panel of clientarea
  var client = getClientArea()
  client.size = main.size
  add back panel to client.children
.

// show buttons for leader only
function setLeaderButtons()
  var main = getMainWindowClass()
  main.size.y += 25
  panel as NodeRef of Class GUIPanel = FindGuiControlByName(main,"Butpanel")
  panel.visible = true
  panel.position.y = main.size.y - 25
.

// grey out the player values - player in diff area
function greyPlayerPanel(num as Integer)
  var panel = getGroupCharPanel(num)
  slider as NodeRef of Class GUIControl
  lbl as NodeRef of Class GUILabel
  color as Class rgba = MiscUtils:MakeRGBA(0.5,0.5,0.5,1)

  // HP slider
  slider = FindGUIControlByName(panel, "HealthPanel.HealthSlider")
  slider.defaultStatePresentation.color = color
  lbl = FindGUIControlByName(panel, "HealthPanel.text")
  lbl.text = ""

  // mana slider
  slider = FindGUIControlByName(panel, "ManaPanel.ManaSlider")
  slider.defaultStatePresentation.color = color
  lbl = FindGUIControlByName(panel, "ManaPanel.text")
  lbl.text = ""
.

// set player listeners - main panel
function setListeners(player as NodeRef of Class E_playerCharacter, charbar as NodeRef of Class TMP_StatusBar)
//  $LightweightEvents.addLightweightEventListener(player, "lvlUpdated", charbar)   // level not used here
  $LightweightEvents.addLightweightEventListener(player, "nameUpdated", charbar)
  $LightweightEvents.addLightweightEventListener(player, "hpUpdated", charbar)
  $LightweightEvents.addLightweightEventListener(player, "manaUpdated", charbar)

  // set init values in
  charbar.SetName(player.name)
  charbar.SetHitP(player.E_hitPoints, player.E_MaxHP)
  charbar.SetMana(player.E_manaPoints, player.E_MaxMP)
.

//=====================================
// get main window class for variables
function getMainWindowClass() as NodeRef of Class TMP_GroupWindow
  return FindGuiControlByName(None,"game.TMP_GroupWindow")
.

function getClientArea() as NodeRef of Class GUIControl
  return FindGuiControlByName(None,"game.TMP_GroupWindow.clientarea")
.

// get group area
function getGroupPanelName(i as String) as NodeRef of Class GUILabel
  return FindGuiControlByName(None, "game.TMP_GroupWindow.clientarea.Member"+ i +".nameLabel")
.

// get char Panel
function getGroupCharPanel(i as String) as NodeRef of Class TMP_StatusBar
  return FindGuiControlByName(None, "game.TMP_GroupWindow.clientarea.Member"+ i)
.

function getGroupPanel(target as NodeRef of Class GUIControl) as NodeRef of Class TMP_StatusBar
  if target.name = "Button"
    if SubString(target.parent.parent.name,1,6) = "member"
      return target.parent.parent
    .
  .
  return None
.
« Last Edit: Feb 03, 16, 11:59:54 PM by Thazager »
Logged
Lead scripter for EO, Repop helper.
HSL Video tutorials:
https://community.heroengine.com/forums/index.php/topic,1719.msg36858.html#msg3685

Thazager

  • General Accounts
  • *
  • Posts: 1160
  • Never stop learning
    • View Profile
Re: Goups - basic
« Reply #3 on: Feb 04, 16, 12:00:35 AM »

*continued from above (max chars on post 20k)
part3

In new (client side) script TMP_InviteWindow

Code: [Select]
// make window for warning
shared function Start()
  var win = getInviteClass()
  if win <> None
    DestroyNode(win)
  .
  win = CreateNodeFromPrototype("TMP_InviteWindow")
  win.build = true
  MiscUtils:CenterWindow(win)
.

// send "target" player invite to group
// player is target in window
public function SendInvite()
  if checkPlayerLeading()     // leader only function
    // get target
    var main = getTargetClass()
    target as NodeRef = main.tmp_target

    if checkFullGroup() = false    // not full
      if target = None
        TMP_GroupMesgs:NoPlayerMesg()
      else
        where target
          is kindof E_playerCharacter
            contSendInvite(target.name)
          .
          is kindof E_nonplayerCharacter
            TMP_GroupMesgs:NPCTargetMesg(target.name)
          .
        .
      .
    else
      where target is kindof E_playerCharacter
        TMP_GroupMesgs:FullGroupMesg(target.name)
      .
    .
  else
    TMP_GroupMesgs:NotLeaderMesg()
  .
.

// get invite from server
// called from server
remote function ReceiveInvite(name as String)
  var win = getInviteClass()
  if win = None
    Start()                 // 1st invite
    win = getInviteClass()  // get pointer
    win.tmp_InviteSender = name   // save player

    var lbl = getPanelName()      // add inviter's name
    lbl.text = name
  else
    var char = MiscUtils:getCharPointer()
///**    call server TMP_GroupsClassMethods:PendingInvite(name, char.name)
  .
.

// tell sender to hold for pending invite
// called from server
remote function ReceiveHold(name as String)
  $CHAT.sendTell(name +" is thinking of joining another group.", "Game")   // already has an invite pending
.

// tell group we accept
function acceptInvite()
  var win = getInviteClass()
  SendName as String = win.tmp_InviteSender   // get player who invited

  var char = MiscUtils:getCharPointer()
  JoinName as String = char.name
///**  call server TMP_GroupsClassMethods:AddPlayerToGroup(SendName, JoinName)
.

// check which button clicked
method _OnButtonMouseClick(button as NodeRef of Class _GUIButton, args references Class GUIMouseEvent)

  if args.leftButton
    when button.name
      is "accept"
        acceptInvite()
        destroynode(me)       // remove it
      .
      is "decline"
        destroynode(me)       // remove it
      .
    .
  .
.

//=================================================================================================
// invite player using /invite
// called from server to check other info
remote function CheckingInvite(name as String)
  if checkPlayerLeading()     // leader only function
    if checkFullGroup() = false    // not full
      contSendInvite(name)
    else
      TMP_GroupMesgs:FullGroupMesg(name)
    .
  else
    TMP_GroupMesgs:NotLeaderMesg()
  .
.

// called after checking settings
function contSendInvite(name as String)
  var char = MiscUtils:getCharPointer()
  target as NodeRef
  JoinName as String = name

  // check if target panel active
  var main = getTargetClass()
  if main <> None
    target = main.tmp_target
    where target is kindof E_CommonCharacter
      JoinName = target.name
    .
  .

  // target = self?
  if JoinName = char.name
    TMP_GroupMesgs:SelfInviteMesg()
    return
  .
  // player in our group?
  if TargetInOurGroup(JoinName) = true
    TMP_GroupMesgs:PlayerInOurGroupMesg(JoinName)
    return
  else
    // player in other group?
    if TargetInOtherGroup(JoinName, target) = true
      TMP_GroupMesgs:PlayerInOtherGroupMesg(JoinName)
      return
    .
  .
  // good for invite
  TMP_GroupMesgs:InvitePlayerMesg(JoinName)
///**  call server TMP_GroupsClassMethods:GroupInvitePlayer(char.name, JoinName)    // player
.

//=================================================================================================
// player joins group - invite by target or name
// called from server (for Leader)
remote function JoinGroup(JoinName as String, info as String)
  if checkFullGroup() == false
    getOpenSeat(info)
    TMP_GroupMesgs:JoinGroupMesg(JoinName)
  else
    TMP_GroupMesgs:FullGroupMesg(JoinName)
  .
.

// check if this player is the leader of the group
// good if player is solo
public function checkPlayerLeading() as Boolean
  var char = MiscUtils:getCharPointer()
  members as List of String = char.tmp_groupPlayers      // members of this group

  // acct / areaName / area / instance / name / level
  dataList as List of String = MiscUtils:getGroupData(members[1])   // leader's info
  name as String = dataList[5]

  if name = char.name          // this player is leader?
    return true
  .
  return false
.

// check if player in our group
// members = our group info
function TargetInOurGroup(JoinName as String) as Boolean
  var char = MiscUtils:getCharPointer()
  members as List of String = char.tmp_groupPlayers      // members of this group

  // acct / areaName / area / instance / name / level
  dataList as List of String

  foreach info in members
    if info <> ""
      dataList = MiscUtils:getGroupData(info)   // current member info

      if (JoinName == dataList[5])   // player is in group
        return true
      .
    .
  .
  return false
.

// check if player already in group
function TargetInOtherGroup(JoinName as String, target as NodeRef) as Boolean
  members as List of String
  where target is kindof E_playerCharacter
    members = target.tmp_groupPlayers
  .
  amount as Integer

  foreach info in members
    if info <> ""
      amount += 1
    .
  .

  // check if player in any group
  if amount > 1
    return true
  .
  return false
.

// see if group is full
function checkFullGroup() as Boolean
  var amount = TMP_GroupWindowClassMethods:getGroupAmount()
  if amount < TMP_GroupWindowClassMethods:getGroupMax()
    return false
  .
  return true
.

// add player to empty spot in group
function getOpenSeat(JoinData as String)
  var char = MiscUtils:getCharPointer()
  members as List of String = char.tmp_groupPlayers
  var amount = TMP_GroupWindowClassMethods:getGroupMax()

  // 5 players in group
  loop i from 1 to amount
    if members[i] = ""      // no info here?
      members[i] = JoinData // place for new player
      break
    .
  .
  char.tmp_groupPlayers = members      //save data
///**  call server TMP_GroupsClassMethods:sendGroupDataToGroup(members, "join", "")
.

//=================================================================================================
function getInviteClass() as NodeRef of Class TMP_InviteWindow
  return FindGUIControlByName(None, "game.TMP_InviteWindow")
.

function getPanelName() as NodeRef of Class GUILabel
  return FindGuiControlByName(None, "game.TMP_InviteWindow.Namelabel")
.

function getTargetClass() as NodeRef of Class E_targetStatusBar
  return FindGUIControlByName(None, "game.targetStatusBar")
.

In new (server side) script TMP_Groups

Code: [Select]
//=============================================================================================================
// INVITE
//=============================================================================================================
// group sending invite to player
// used for command /invite player
public function GroupSendInvite(accountID as ID, SendName as String, ReceiveName as String)
  call client accountID TMP_InviteWindowClassMethods:CheckingInvite(SendName)
.

// send the invite to the player
// in senders area
// used for target invite , window invite , /invite name
untrusted remote method GroupInvitePlayer(SendName as String, ReceiveName as String)
  call area 0 instance 0 GroupInvitePlayerUsingName(SendName, ReceiveName)
.

// find player using name
// in world server area 0
remote function GroupInvitePlayerUsingName(SendName as String, ReceiveName as String)
  ReceiveID as ID = LookupPlayerAccountID(ReceiveName)
  area as ID
  instance as ID
  WhereIsPlayer(ReceiveID, area, instance)

  call area area instance instance GroupInviteThisPlayer(SendName, ReceiveID)
.

// send the team invite to player
// in receivers area
remote function GroupInviteThisPlayer(SendName as String, ReceiveID as ID)
  call client ReceiveID TMP_InviteWindowClassMethods:ReceiveInvite(SendName)
.

//=============================================================================================================
// Pending INVITE
//=============================================================================================================
// player has pending invite, let sender know
// in receivers area
untrusted remote method PendingInvite(SendName as String, PlayerName as String)
  call area 0 instance 0 PendingInvitePlayerUsingName(SendName, PlayerName)
.

// find player using name
// in world server area 0
remote function PendingInvitePlayerUsingName(SendName as String, PlayerName as String)
  SendID as ID = LookupPlayerAccountID(PlayerName)
  area as ID
  instance as ID
  WhereIsPlayer(SendID, area, instance)

  call area area instance instance PendingInviteHold(SendID, PlayerName)
.

// tell sender Hold for pending invite
// in senders area
remote function PendingInviteHold(SendID as ID, PlayerName as String)
  call client SendID TMP_InviteWindowClassMethods:ReceiveHold(PlayerName)
.

//=============================================================================================================
// Accept INVITE
//=============================================================================================================
// player accepts invite
// in joiners area
untrusted remote method AddPlayerToGroup(SendName as String, JoinName as String)
  call area 0 instance 0 AddPlayerUsingName(SendName, JoinName)
.

// find player using name
// in world server area 0
remote function AddPlayerUsingName(SendName as String, JoinName as String)
  SendID as ID = LookupPlayerAccountID(SendName)
  area as ID
  instance as ID
  WhereIsPlayer(SendID, area, instance)

  JoinID as ID = LookupPlayerAccountID(JoinName)
  area2 as ID
  instance2 as ID
  WhereIsPlayer(JoinID, area2, instance2)

  call area area2 instance instance2 PlayerJoinGroup(SendID, JoinName, JoinID, area, instance)
.

// get joiner info
// in joiners area
remote function PlayerJoinGroup(SendID as ID, JoinName as String, JoinID as ID, area as ID, instance as ID)
  JoinData as String = getPlayerGroupInfo(JoinID)
  call client JoinID TMP_GroupMesgs:GroupJoin()    // feedback
  call area area instance instance PlayerJoinThisGroup(SendID, JoinName, JoinData)
.

// player joins group
// in senders area
remote function PlayerJoinThisGroup(SendID as ID, JoinName as String, JoinData as String)
  call client SendID TMP_InviteWindowClassMethods:JoinGroup(JoinName, JoinData)
.

//=============================================================================================================
// kick player from group
//=============================================================================================================
// remove player from group
// in leaders area
untrusted remote method RemovePlayerFromGroup(playerName as String, info as String)
  call area 0 instance 0 RemovePlayerUsingName(playerName, info)
.

// find player using name
// in world server area 0
remote function RemovePlayerUsingName(playerName as String, info as String)
  playerID as ID = LookupPlayerAccountID(PlayerName)
  area as ID
  instance as ID
  WhereIsPlayer(playerID, area, instance)

  call area area instance instance PlayerRemoveGroup(playerID, info)
.

// player leaves group
// in players area
remote function PlayerRemoveGroup(playerID as ID, info as String)
  call client playerID TMP_GroupWindowClassMethods:KickGroup(info)
.

//=============================================================================================================
// player changes areas
//=============================================================================================================
// called from E_Account
// player changes areas - tell group
public function tellGroupIMoved(accountID as ID)
  acct as NodeRef of Class E_playerAccount = accountID
  char as NodeRef of Class E_playerCharacter = acct.GetMyChar()
  members as List of String = char.tmp_groupPlayers

  sendGroupData(members, "info", char.name)
.

//=============================================================================================================
// player data - keeping the group informed of changes
//=============================================================================================================
// send player location to client
// set everytime player changes areas
untrusted remote method getPlayerGroupValues()
  accountID as ID = SYSTEM.REMOTE.client
  data as String = getPlayerGroupInfo(accountID)
  call client accountID TMP_GroupWindowClassMethods:InitGroupValues(data)
.

// gather player data for group
// in players area
function getPlayerGroupInfo(accountID as ID) as String
  acct as NodeRef of Class E_playerAccount = accountID
  char as NodeRef of Class E_playerCharacter = acct.GetMyChar()

  area as ID = char._currentArea
  instance as ID = char._currentAreaInstance
  areaName as String = GetAreaName(area)
  level as String = char.E_level

  // acct / areaName / area / instance / name / level
  data as String = ""+ accountID +","
  data += areaName +","
  data += area +","
  data += instance +","
  data += char.name +","
  data += level

  char.tmp_groupMe = data
  return data
.

//=============================================================================================================
// sending data to all our group members
//=============================================================================================================
// get data from group with new data
untrusted remote method sendGroupDataToGroup(members as List of String, process as String, name as String)
  acct as NodeRef of Class E_playerAccount = SYSTEM.REMOTE.client
  char as NodeRef of Class E_playerCharacter = acct.GetMyChar()

  newName as String = name
  if process = "quit"
    newName = char.name   // which player is quitting
  .
  sendGroupData(members, process, newName)
.

// send data to each member
function sendGroupData(members as List of String, process as String, name as String)
  dataList as List of String
  foreach val in members
    if val = ""
      break       // all done
    .
    // acct / areaName / area / instance / name / level
    dataList = getGroupData(val)  // get player info

    clientID as ID = dataList[1]
    areaID as ID = dataList[3]
    instanceID as ID = dataList[4]

    call area areaID instance instanceID sendingGroupData(clientID, members, process, name)
  .
.

// send data to player in group
// in members area
remote function sendingGroupData(clientID as ID, members as List of String, process as String, name as String)
  when process
    is "save"
      call client clientID TMP_GroupWindowClassMethods:saveGroupMemberData(members)
    .
    is "join"
      call client clientID TMP_GroupWindowClassMethods:JoinThisGroup(members)
    .
    is "quit"
      call client clientID TMP_GroupWindowClassMethods:PlayerLeftGroup(members, name)
    .
    is "kick"
      call client clientID TMP_GroupWindowClassMethods:PlayerKickGroup(members, name)
    .
    is "lead"
      call client clientID TMP_GroupWindowClassMethods:NewPlayerLeader(members, name)
    .
    is "info"
      call client clientID TMP_GroupWindowClassMethods:ChangeAreas(members, name)
    .
  .
.

//=============================================================================================================
// break string into parts
// uses comma so that can be part of list of strings
public function getGroupData(info as String) as List of String
  infoList as List of String
  SplitBy(info, ",", infoList)      // acct / areaName / area / instance / name / level
  return infoList
.

// save player data for group
untrusted remote method savePlayerGroupValues(members as List of String)
  acct as NodeRef of Class E_playerAccount = SYSTEM.REMOTE.client
  char as NodeRef of Class E_playerCharacter = acct.GetMyChar()
  char.tmp_groupPlayers = members
.
Logged
Lead scripter for EO, Repop helper.
HSL Video tutorials:
https://community.heroengine.com/forums/index.php/topic,1719.msg36858.html#msg3685