Files
dsrc/sku.0/sys.server/compiled/game/script/grouping/group_object.script
T

391 lines
12 KiB
Plaintext

/**
* Copyright (c)2000-2002 Sony Online Entertainment Inc.
* All Rights Reserved
*
* Title: group_object.script
* Description: script for the group object
* @author $Author:$
* @version $Revision:$
*/
/***** INCLUDES ********************************************************/
include java.util.Hashtable;
include java.util.Set;
include java.util.Iterator;
trigger OnInitialize()
{
return SCRIPT_CONTINUE;
}
/***** INHERITS ********************************************************/
/***** CONSTANTS *******************************************************/
/***** TRIGGER *********************************************************/
/***** MESSAGEHANDLERS **************************************************/
messageHandler volleyTargetDone()
{
//LOG("combat", "Group object " + self + " received volleyTargetDone message.");
obj_id[] members = getGroupMemberIds(self);
if(members == null || members.length < 1)
{
//LOG("combat", "No members in group. Not messaging any members.");
return SCRIPT_CONTINUE;
}
for(int i = 0; i < members.length; i++)
{
//LOG("combat", "Messaging 'volleyTargetDone' to " + members[i]);
messageTo(members[i], "volleyTargetDone", params, 0, false);
}
return SCRIPT_CONTINUE;
}
messageHandler addGroupMember()
{
// check the messageTo dictionary parameters
if(params != null)
{
// the group member is set in group_member.script
obj_id newGroupMember = params.getObjId("memberObjectId");
if(isIdValid(newGroupMember))
{
deltadictionary scriptVars = self.getScriptVars();
if(scriptVars != null)
{
// the new member might have missions closer
// for the group, run through the mssion select
// logic
selectNearestGroupMission(self);
}
}
}
return SCRIPT_CONTINUE;
}
messageHandler removeGroupMember()
{
if(params != null)
{
// set in group_member.script
obj_id groupMember = params.getObjId("sender");
if(isIdValid(groupMember))
{
deltadictionary scriptVars = self.getScriptVars();
if(scriptVars != null)
{
// the group member might have had the
// mission closest to the group. Run the
// group mission waypoint selection
selectNearestGroupMission(self);
}
}
}
return SCRIPT_CONTINUE;
}
location calculateNearestGroupMission(obj_id self)
{
// iterate through the members and mission locations
// retrieved from the members. Each member 'votes' for
// the mission that is nearest to them. The location with
// the most 'votes' becomes the new group mission objective
location result = new location();
deltadictionary scriptVars = self.getScriptVars();
if(scriptVars != null)
{
// get the memberLocations and the missionLocations,
// bail out of either of them are empty (nothing to vote on)
location[] memberLocations = scriptVars.getLocationArray("memberLocations");
if((memberLocations == null) || (memberLocations.length < 1))
{
return null;
}
location[] missionLocations = scriptVars.getLocationArray("missionLocations");
if((missionLocations == null) || (missionLocations.length < 1))
{
return null;
}
// initialize the nearestGroupMission if it already exists
location nearestGroupMission = scriptVars.getLocation("nearestGroupMission");
if(nearestGroupMission == null)
{
if(missionLocations.length > 0)
{
// no nearestGroupMission, start with the first mission
// in the locations list
nearestGroupMission = missionLocations[0];
}
else
{
return null;
}
}
// this map contains the vote results. It's a map of locations and vote counts
// (int location, int votes)
Hashtable bestLocations = new Hashtable();
// outer loop iterates over the members
int memberLocationIndex = 0;
int preferredIndex = -1;
for(memberLocationIndex = 0; memberLocationIndex < memberLocations.length; ++memberLocationIndex)
{
int missionLocationIndex = 0;
//location memberPreferredLocation = nearestGroupMission;
float bestDistance = -1;
// inner loop iterates over mission locations
for(missionLocationIndex = 0; missionLocationIndex < missionLocations.length; ++missionLocationIndex)
{
// initialize the location under consideration
location currentLocation = missionLocations[missionLocationIndex];
// verify that the mission being considered is on the same
// planet as the group member
if(currentLocation.area.equals(memberLocations[memberLocationIndex].area))
{
// check the distance between the current location under consideration
// and the best candidate found so far
float currentDistance = currentLocation.distance(memberLocations[memberLocationIndex]);
if(bestDistance < 0 || currentDistance < bestDistance)
{
// the current mission is better, promote it to the
// 'best' candidate location
preferredIndex = missionLocationIndex;
bestDistance = currentDistance;
}
}
}
if(preferredIndex > -1)
{
Integer p = new Integer(preferredIndex);
// add the most preferred candidate location to the voting results map
if(bestLocations.containsKey(new Integer(preferredIndex)))
{
int votes = ((Integer)bestLocations.get(p)).intValue();
votes = votes + 1;
bestLocations.put(p, new Integer(votes));
}
else
{
Integer votes = new Integer(1);
bestLocations.put(p, votes);
}
}
}
// tally the votes for the new nearest group mission
Set keySet = bestLocations.keySet();
Iterator votesIterator = keySet.iterator();
int mostVotes = 0;
while(votesIterator.hasNext())
{
Integer locationIndex = (Integer)(votesIterator.next());
//location l = (location)votesIterator.next();
int votes = ((Integer)bestLocations.get(locationIndex)).intValue();
// this location has the most votes(so far)
if(votes > mostVotes)
{
nearestGroupMission = missionLocations[locationIndex.intValue()];
mostVotes = votes;
}
}
// update the nearest group mission waypoint for everyone in the group
result = nearestGroupMission;
scriptVars.put("nearestGroupMission", nearestGroupMission);
}
else
{
result = null;
}
return result;
}
messageHandler missionLocationResponse()
{
// group_member.script has responded to a request
// for mission location information
if((params != null) && (params.containsKey("requestMissionLocationsNumber")))
{
deltadictionary scriptVars = self.getScriptVars();
if((scriptVars != null) && (scriptVars.hasKey("requestMissionLocationsNumber")) && (params.getInt("requestMissionLocationsNumber") == scriptVars.getInt("requestMissionLocationsNumber")))
{
// retrieve mission and member information
// from the script parameter dictionary
obj_id missionHolder = params.getObjId("sender");
if(isIdValid(missionHolder))
{
// get the location of the group member
location senderLocation = params.getLocation("senderLocation");
if(senderLocation != null)
{
// match against other group member locations
// and member mission locations, update the
// nearest group mission and waypoint if necessary
resizeable location[] memberLocations = scriptVars.getResizeableLocationArray("memberLocations");
if(memberLocations == null)
{
memberLocations = new Vector();
}
memberLocations.add(senderLocation);
scriptVars.put("memberLocations", memberLocations);
location[] missionLocation = params.getLocationArray("missionLocation");
if((missionLocation != null) && (missionLocation.length > 0))
{
// mission locations are used in the
// group calculation (see comments in
// calculateNearestGroupMission
resizeable location[] missionLocations = scriptVars.getResizeableLocationArray("missionLocations");
if(missionLocations == null)
{
missionLocations = new Vector();
}
for(int i = 0; i < missionLocation.length; ++i)
{
missionLocations.add(missionLocation[i]);
}
scriptVars.put("missionLocations", missionLocations);
location nearestGroupMission = scriptVars.getLocation("nearestGroupMission");
if(nearestGroupMission == null)
{
nearestGroupMission = missionLocation[0];
scriptVars.put("nearestGroupMission", nearestGroupMission);
}
}
// once all group members have reported, execute the nearestGroupMission
// calculation and disseminate the results to group members; if members
// may have joined or left the group while we were accumulating the
// information which may cause what we have accumulated to be out of
// sync with the actual state of the group, don't worry about it, since
// we recalculate whenever someone joins or leaves the group
if (memberLocations.length >= getPCGroupSize(self))
tellMembersAboutNearestGroupMission(self, calculateNearestGroupMission(self));
}
}
}
}
return SCRIPT_CONTINUE;
}
void tellMembersAboutNearestGroupMission(obj_id self, location nearestGroupMission)
{
// bail out early if no nearestGroupMission is available
if(nearestGroupMission != null)
{
deltadictionary scriptVars = self.getScriptVars();
if(scriptVars != null)
{
// update the nearest group mission waypoint for everyone in the group
// get the members list from scriptVars, use it to dispatch messageTo's
obj_id[] members = getGroupMemberIds(self);
int memberIndex = 0;
// create the messageTo parameters dictionary and put the
// nearestGroupMission location in it
dictionary msgData = new dictionary();
msgData.put("waypointLocation", nearestGroupMission);
// work around a bug/shortcoming of the messaging system. messageTo's
// are delivered out of sequence in a seemingly random fashion. To
// ensure that only the most recent update is applied, add a sequence
// to the message. group_member.script's messageHandler will discard
// messages with sequence values less than what it has already
// received.
int sequence = scriptVars.getInt("updateSequence");
sequence++;
scriptVars.put("updateSequence", sequence);
msgData.put("updateSequence", sequence);
// now iterate over the members list and send an updateGroupWaypoint
// messageTo with the sequence and nearestGroupMission location
for(memberIndex = 0; memberIndex < members.length; ++memberIndex)
{
messageTo(members[memberIndex], "updateGroupWaypoint", msgData, 0, false);
}
}
}
}
void selectNearestGroupMission(obj_id self)
{
// starts the nearestGroupMission location
// selection protocol from scracth, removing
// the current nearestGroupMission locatio
// and replacing it with the best location
deltadictionary scriptVars = self.getScriptVars();
if(scriptVars != null)
{
// clear out old mission and member location data
// this will be refreshed by group member's responding
// to the requestMissionLocations message
scriptVars.remove("memberLocations");
scriptVars.remove("missionLocations");
scriptVars.remove("nearestGroupMission");
// iterate over the group members list and
// deliver the requestMissionLocations message.
// group_member.script will query its owner's
// mission objects for location information
obj_id[] members = getGroupMemberIds(self);
if(members != null)
{
// a counter to map responses to requestMissionLocations;
// we use this in cases where selectNearestGroupMission() is called
// before we have received all responses to a previous
// selectNearestGroupMission() call, in which case, we'll throw
// out the "stale" responses to requestMissionLocations
int requestMissionLocationsNumber = 1;
if (scriptVars.hasKey("requestMissionLocationsNumber"))
{
requestMissionLocationsNumber = scriptVars.getInt("requestMissionLocationsNumber");
++requestMissionLocationsNumber;
}
scriptVars.put("requestMissionLocationsNumber", requestMissionLocationsNumber);
dictionary requestData = new dictionary();
requestData.put("requestMissionLocationsNumber", requestMissionLocationsNumber);
int memberIndex = 0;
for(memberIndex = 0; memberIndex < members.length; ++memberIndex)
{
messageTo(members[memberIndex], "requestMissionLocations", requestData, 0, false);
}
}
}
}
messageHandler recaclulateNearestGroupWaypoint()
{
// this message is received from a group member
// when it has been notified that one of its
// mission waypoints has been updated
selectNearestGroupMission(self);
return SCRIPT_CONTINUE;
}
messageHandler removeMissionLocation()
{
// this message is sent by a group member
// when a mission object is no longer
// available (it's been removed, finished,
// incomplete, aborted, etc.)
selectNearestGroupMission(self);
return SCRIPT_CONTINUE;
}