Author Topic: Need help with area partying only!  (Read 812 times)

Legacy_Holy Ronin

  • Newbie
  • *
  • Posts: 33
  • Karma: +0/-0
Need help with area partying only!
« on: February 17, 2016, 10:36:46 am »


               

Hello NWN community,


 


I'm trying to find a script for blocks players form partying up when they are not in the same area.


 


 


It's something pretty simple and I'm sure one of you guys knows where, or can find out where to get something like this.


 


Thanks,


 


Holy Ronin



               
               

               
            

Legacy_henesua

  • Hero Member
  • *****
  • Posts: 6519
  • Karma: +0/-0
Need help with area partying only!
« Reply #1 on: February 17, 2016, 01:58:04 pm »


               

I do not believe that there is a simple way to achieve this.


 


Aside from the technical problems, I also don't think doing this is a good idea. Before making this scipt, you will need to be very clear as to exactly what you are trying to achieve with this, and determine the precise way to do it without interferring with partying up under other circumstances (such as one player transitioning to a new area before the rest of the party and thus being kicked from the party).



               
               

               
            

Legacy_Holy Ronin

  • Newbie
  • *
  • Posts: 33
  • Karma: +0/-0
Need help with area partying only!
« Reply #2 on: February 17, 2016, 07:13:01 pm »


               

Players transitioning from area to area with the party is not the issue. The issue is players who are.. not near each other partying for purposes of cheating. What i'm trying to achieve is to prevent players from partying solely through the player menu. I would like players who are physically near each other to be able to party only. To keep people who are not physically near each other from partying.


 


The reason for this issue is because we have a unique system of traveling that brings up an issue of saving each other from danger through partying without being physically near each other.



               
               

               
            

Legacy_henesua

  • Hero Member
  • *****
  • Posts: 6519
  • Karma: +0/-0
Need help with area partying only!
« Reply #3 on: February 17, 2016, 08:18:56 pm »


               

I raised those points so that you are very clear as to how you will implement this to meet your precise needs. I appreciate you letting me know, but its you and your team that need to know, and be very clear.


 


For example: depending on how you implement this (if its possible in an elegant way) it may become a problem when players move their PCs to different areas.


 


Anyway, someone that has an idea as to how best to solve this, will have to speak up. I have little interest in implementing this myself, so I don't have my head around the best way to solve this. i'll be lurking to see how the conversation goes and offer advice or code snippets if inspiration strikes.



               
               

               
            

Legacy_Holy Ronin

  • Newbie
  • *
  • Posts: 33
  • Karma: +0/-0
Need help with area partying only!
« Reply #4 on: February 18, 2016, 03:31:06 am »


               

Thanks



               
               

               
            

Legacy_Holy Ronin

  • Newbie
  • *
  • Posts: 33
  • Karma: +0/-0
Need help with area partying only!
« Reply #5 on: February 18, 2016, 06:34:38 am »


               

Ok new question,


 


I'm trying to find the script command that refers to a player who is the person being invited to a party, not the one sending the invitation.


 


We know that: (oTarget) is the one inviting, what is the command or line for the one who is being invited?



               
               

               
            

Baaleos

  • Administrator
  • Hero Member
  • *****
  • Posts: 1916
  • Karma: +0/-0
Need help with area partying only!
« Reply #6 on: February 18, 2016, 11:41:36 am »


               

In order to achieve this, you would need to use nwnx at the very least in order to block the partying invite (I've made a hook in the past that fired on party invites etc)


Not sure I still have it, it was a little unstable tbh - someone better than me could definitely achieve it though.


 


The non-nwnx alternative is to modify the modules heartbeat to perform party checks at regular intervals.


 
//oSource is the player being processed, oTarget is the party member they are being compared to
void ProcessPartyMember(object oSource, object oTarget)
{
object oSourceArea = GetArea(oSource);
object oTargetArea = GetArea(oTarget);
     if(oTargetArea == OBJECT_INVALID || oSourceArea==OBJECT_INVALID)
{
//If either player is zoning - give them a free pass on this occasion
return;
}
int iCounter1 = GetLocalInt(oSource,"NOT_WITH_PARTY_COUNTER");
int iCounter2 = GetLocalInt(oTarget,"NOT_WITH_PARTY_COUNTER");
 
if(oTargetArea != oSourceArea)
{
//Both players are in different areas
//Now what do we do?
//Maybe its a temporary issue - they might be 20 seconds behind us.
//Incremement a counter
iCounter1++;
iCounter2++;
 
}else
{
//If they are with the party, they have their counter reset.
iCounter1 = 0;
iCounter2 = 0;
}
 
//Store the values so we can increment later
SetLocalInt(oSource,"NOT_WITH_PARTY_COUNTER",iCounter1);
SetLocalInt(oTarget,"NOT_WITH_PARTY_COUNTER",iCounter2);
if(iCounter1 >= 25)
{
RemoveFromParty(oSource);
}
if(iCounter2 >= 25)
{
RemoveFromParty(oTarget);
}
}
 
void ProcessPlayer(object oPlayer)
{
     object oPartyMember = GetFirstFactionMember(oPlayer,TRUE);
while(oPartyMember != OBJECT_INVALID)
{
ProcessPartyMember(oPlayer,oPartyMember);
oPartyMember = GetNextFactionMember(oPlayer,TRUE);
}
);
 
 
}
//heartbeat.nss
void main()
{
 
//Normal Heartbeat script stuff here
object oPC = GetFirstPC();
while(oPC != OBJECT_INVALID)
{
ProcessPlayer(oPC);
oPC = GetNextPC();
}
 
 
}
 

               
               

               
            

Legacy_Holy Ronin

  • Newbie
  • *
  • Posts: 33
  • Karma: +0/-0
Need help with area partying only!
« Reply #7 on: February 19, 2016, 12:09:38 am »


               

Ok,


 


This would be good, However there is still room for exploiting with this;


 


We have nwnx; Now..  Could you help us create a conditional to block the party invite if players are not in the same area?



               
               

               
            

Baaleos

  • Administrator
  • Hero Member
  • *****
  • Posts: 1916
  • Karma: +0/-0
Need help with area partying only!
« Reply #8 on: February 19, 2016, 04:56:16 pm »


               

I don't know when I will have a chance to work on that.


I just reinstalled my computer due to a botched upgrade to windows 10 - so all the tools I would need for building it are gone.



               
               

               
            

Legacy_Thayan

  • Sr. Member
  • ****
  • Posts: 435
  • Karma: +0/-0
Need help with area partying only!
« Reply #9 on: February 19, 2016, 06:31:55 pm »


               

Why not address whatever this travel exploit is? Since you're going to close it anyway, can you tell us what are people doing to exploit your system? There has to be another way than relying on a NWNX plugin to resolve your problem.


 


Although I have no clue what your exploit is though; as just a rough idea, you could run a psuedoheartbeat whenever someone starts to use your travel feature, which would first mark whoever is a PC member of their party (use the GetFirstFactionMember() function with the bPCOnly flag set to true), and in their current area, as a valid member of their party. Then run the psudeoheartbeat check every 6 seconds (or however often you feel is necessary to stop someone from trying this exploit) and if someone is a member of their party who was not marked as such when the psuedoheartbeat started, they get booted from it via the RemoveFromParty() function.



               
               

               
            

Legacy_Holy Ronin

  • Newbie
  • *
  • Posts: 33
  • Karma: +0/-0
Need help with area partying only!
« Reply #10 on: February 19, 2016, 10:47:34 pm »


               

We have certain areas in our module that are considered random areas. In order for the players to begin randomly traveling they step on a waypoint whose script rolls dice to determine what waypoint they will go to. The script sends the entire party to the area

 

Our first solution is to add "case EVENT_TYPE_PARTY_INVITE:" as a function in the NWNX custom events to add a condition where party invitations are bypassed via "BypassEvent ( );" when the PC inviting and the target being invited are not in the same area.

 

 Our second solution could be to edit the script activated when a PC steps in to the waypoint leading to the random areas, so that when sending the party, the script will first check to see if all party members are within a certain distance of the PC traveling; if not, then it could use an "else" statement to send the PC alone, boot him/her from the party and say a message like: "You have moved on before gathering your party and have left the others behind."

 

The exploit we are dealing with is that if a PC invites someone who is in a distant location, then upon traveling into the random area, the PC will pull the other person across miles of terrain which is unrealistic, especially if the other player is in a dangerous location.



location lTarget;
object oTarget;

//Put this script OnEnter
void main()
{

object oPC = GetEnteringObject();

if (!GetIsPC(oPC)) return;

if (d100()<=5)
   {
   oTarget = GetWaypointByTag("DesertOasis_W");

   lTarget = GetLocation(oTarget);

//only do the jump if the location is valid.
//check if it is in a valid area.
//the script will stop if the location isn't valid - meaning that
//nothing put after the teleport will fire.

   if (GetAreaFromLocation(lTarget)==OBJECT_INVALID) return;

   oTarget=GetFirstFactionMember(oPC, FALSE);

   while (GetIsObjectValid(oTarget))
      {
      AssignCommand(oTarget, ClearAllActions());

      AssignCommand(oTarget, ActionJumpToLocation(lTarget));
      oTarget=GetNextFactionMember(oPC, FALSE);
      }

   }
else if (d100()<=25)
   {
   oTarget = GetWaypointByTag("DesertRoadNW_W");

   lTarget = GetLocation(oTarget);

//only do the jump if the location is valid.
//check if it is in a valid area.
//the script will stop if the location isn't valid - meaning that
//nothing put after the teleport will fire.

   if (GetAreaFromLocation(lTarget)==OBJECT_INVALID) return;

   oTarget=GetFirstFactionMember(oPC, FALSE);

   while (GetIsObjectValid(oTarget))
      {
      AssignCommand(oTarget, ClearAllActions());

      AssignCommand(oTarget, ActionJumpToLocation(lTarget));
      oTarget=GetNextFactionMember(oPC, FALSE);
      }

   }
else if (d100()<=25)
   {
   oTarget = GetWaypointByTag("DesertRoadEW1_W");

   lTarget = GetLocation(oTarget);

//only do the jump if the location is valid.
//check if it is in a valid area.
//the script will stop if the location isn't valid - meaning that
//nothing put after the teleport will fire.

   if (GetAreaFromLocation(lTarget)==OBJECT_INVALID) return;

   oTarget=GetFirstFactionMember(oPC, FALSE);

   while (GetIsObjectValid(oTarget))
      {
      AssignCommand(oTarget, ClearAllActions());

      AssignCommand(oTarget, ActionJumpToLocation(lTarget));
      oTarget=GetNextFactionMember(oPC, FALSE);
      }

   }
else if (d100()<=25)
   {
   oTarget = GetWaypointByTag("DesertRoadEW2_W");

   lTarget = GetLocation(oTarget);

//only do the jump if the location is valid.
//check if it is in a valid area.
//the script will stop if the location isn't valid - meaning that
//nothing put after the teleport will fire.

   if (GetAreaFromLocation(lTarget)==OBJECT_INVALID) return;

   oTarget=GetFirstFactionMember(oPC, FALSE);

   while (GetIsObjectValid(oTarget))
      {
      AssignCommand(oTarget, ClearAllActions());

      AssignCommand(oTarget, ActionJumpToLocation(lTarget));
      oTarget=GetNextFactionMember(oPC, FALSE);
      }

   }
else if (d100()<=100)
   {
   oTarget = GetWaypointByTag("DesertRoadSW_W");

   lTarget = GetLocation(oTarget);

//only do the jump if the location is valid.
//check if it is in a valid area.
//the script will stop if the location isn't valid - meaning that
//nothing put after the teleport will fire.

   if (GetAreaFromLocation(lTarget)==OBJECT_INVALID) return;

   oTarget=GetFirstFactionMember(oPC, FALSE);

   while (GetIsObjectValid(oTarget))
      {
      AssignCommand(oTarget, ClearAllActions());

      AssignCommand(oTarget, ActionJumpToLocation(lTarget));
      oTarget=GetNextFactionMember(oPC, FALSE);
      }

   }
}

               
               

               
            

Legacy_WhiZard

  • Hero Member
  • *****
  • Posts: 2149
  • Karma: +0/-0
Need help with area partying only!
« Reply #11 on: February 20, 2016, 07:18:48 am »


               


Our second solution could be to edit the script activated when a PC steps in to the waypoint leading to the random areas, so that when sending the party, the script will first check to see if all party members are within a certain distance of the PC traveling; if not, then it could use an "else" statement to send the PC alone, boot him/her from the party and say a message like: "You have moved on before gathering your party and have left the others behind."




 


This, by far, looks to be the easiest implementation, especially if you have an aura to denote the boundaries for the teleportation.


               
               

               
            

Legacy_Holy Ronin

  • Newbie
  • *
  • Posts: 33
  • Karma: +0/-0
Need help with area partying only!
« Reply #12 on: February 20, 2016, 08:15:30 pm »


               

The problem is we don't know how to script auras. Is it possible for you guys to help us with the script or could you point us in the direction to learn how to script auras?


 


Thanks



               
               

               
            

Legacy_Thayan

  • Sr. Member
  • ****
  • Posts: 435
  • Karma: +0/-0
Need help with area partying only!
« Reply #13 on: February 21, 2016, 05:28:06 pm »


               

In looking at your script, you don't need to create an aura. In fact, that script has alot of redundancy and it (seems to?) have a logic error of using "else if (d100()<=25)" three times.


 


Anyway, your particular problem can be addressed by modifying all the sectons of code that look like this:



   while (GetIsObjectValid(oTarget))
      {
      AssignCommand(oTarget, ClearAllActions());
      AssignCommand(oTarget, ActionJumpToLocation(lTarget));
      oTarget=GetNextFactionMember(oPC, FALSE);
      }
   }

To this:



  while (GetIsObjectValid(oTarget)) {
    float fMetersAway = 10.0;
    if (GetIsPC(oTarget) && (GetArea(oTarget) != GetArea(oPC) || GetDistanceBetween(oPC, oTarget) > fMetersAway)) {
      RemoveFromParty(oTarget);
      SendMessageToPC(oPC, "You have moved on before gathering your party, and have left "+GetName(oTarget)+" behind.");
    }
    else {
      AssignCommand(oTarget, ClearAllActions());
      AssignCommand(oTarget, ActionJumpToLocation(lTarget));
    }

    oTarget=GetNextFactionMember(oPC, FALSE);
  }

---


 


HOWEVER, because this script's redundancy and those logic errors bugged me so much I rewrote it for you to something more simplified and fixed the logic errors (assuming they are indeed 'errors'). So just replace all the code in the script you provided with this:



void DoTravel(object oPC, location lTarget);

void main()
{
  object oPC = GetEnteringObject();
  location lTarget;

  if (!GetIsPC(oPC)) return;

  int iRoll = d100(); //Logic error(?) fix recommended by Tchos
  if (iRoll<=5) lTarget = GetLocation(GetWaypointByTag("DesertOasis_W"));
  else if (iRoll<=25) lTarget = GetLocation(GetWaypointByTag("DesertRoadNW_W"));
  else if (iRoll<=50) lTarget = GetLocation(GetWaypointByTag("DesertRoadEW1_W")); //Thayan - Logic error? Changed <=25 to <=50
  else if (iRoll<=75) lTarget = GetLocation(GetWaypointByTag("DesertRoadEW2_W")); //Thayan - Logic Error? Changed <=25 to <=75
  else if (iRoll<=100) lTarget = GetLocation(GetWaypointByTag("DesertRoadSW_W"));

  DoTravel(oPC, lTarget);
}

void DoTravel(object oPC, location lTarget)
{
  //only do the jump if the location is valid.
  //check if it is in a valid area.
  //the script will stop if the location isn't valid - meaning that nothing put after the teleport will fire.
  if (GetAreaFromLocation(lTarget)==OBJECT_INVALID) return;

  object oTarget = GetFirstFactionMember(oPC, FALSE);
  while (GetIsObjectValid(oTarget)) {
    //Thayan - If the oTarget is a PC is not in the same area, or more than fMetersAway meters away, boot them from the party
    float fMetersAway = 10.0; //Thayan - Change this to an acceptable distance a member of the party can be from the entering PC in order to travel with them
    if (GetIsPC(oTarget) && (GetArea(oTarget) != GetArea(oPC) || GetDistanceBetween(oPC, oTarget) > fMetersAway)) {
      RemoveFromParty(oTarget);
      SendMessageToPC(oPC, "You have moved on before gathering all of your party, and have left "+GetName(oTarget)+" behind.");
    }
    else {
      AssignCommand(oTarget, ClearAllActions());
      AssignCommand(oTarget, ActionJumpToLocation(lTarget));
    }

    oTarget=GetNextFactionMember(oPC, FALSE);
  }
}


               
               

               
            

Legacy_Tchos

  • Sr. Member
  • ****
  • Posts: 454
  • Karma: +0/-0
Need help with area partying only!
« Reply #14 on: February 21, 2016, 05:49:19 pm »


               

Do you really need to roll a d100 five times to make a single random choice?  I'd just roll it once, and check the single number it generated against the percentage chance I want to give each choice.