PC, companion, cohorts: terminology and scripting
#1
Posté 08 décembre 2010 - 12:29
I was hoping for some clarification that is used by manuals and community as to the terminolgy of PC, companions, cohorts, and fellow PC's that the player makes(per SoZ)
1. Companions are builder created npc's that can join the PC's party. Are cohorts, introduced in SoZ, the same thing as companions?
2. What are additional PC's created by the player and added to original PC's party(per SoZ) called?
In scripting, how are companions, cohorts, and additional PC's defined and differentiated?
I'm talking about functions like GetIsPC, GetFirstPC, GetFirstInFaction, GetOwnedByPlayer, etc.
Is the player's original PC, and any additional player created PC's in player's party considered the same thing in scripting?
3. Are companions/cohorts considered as PC's for function calls?
4. With GetIsPC, it checks to see if creature is player controlled. Does that mean if that character is in PC's party, whether it be companion, cohort, or additional PC, that it would return true, as long as the player has clicked on that character?
5.With GetIsOwnedByPlayer, I would think that is only for the original PC and additional player created PC's; not any companions/cohorts even if that companion/cohort is currently clicked on.
Thanks in advance for any insight given.
#2
Posté 08 décembre 2010 - 12:43
SoZ introduced the ability to import (and later export) your own custom party (shamelessly copying Icewind Dale II), however I believe the party leader is always the 'FirstPC' (and 'FirstInFaction' and 'FactionLeader') while others are simply faction/roster members like any other 'companion'. It's just that you have more control over their creation and advancement.
I had the impression that GetIsOwnedByPlayer only returned true for their animal companion (druids, rangers, clerics with the 'animal' domain), wizard familiars, or summoned creatures (and perhaps dominated creatures?). I don't think roster members count as being 'owned' by the PC (unlike 'Henchmen' in NWN1). Someone please correct me if I'm wrong there.
Modifié par DannJ, 08 décembre 2010 - 12:44 .
#3
Posté 08 décembre 2010 - 05:06
I call the party members created via the party editor "player-created party members".
Scriptwise the differences are that standard companions and associates will have tags, but player-created party members do not have tags. The main PC also does not have a tag. You can tell the difference between the main PC and the player-created party members by checking the roster. All of them will be in the faction, but the main PC is not in the roster.
In the King's Festival campaign I have a debug item called the State of the Party Report that prints out information about the party using the following scripts:
// ginc_bb_stringlib
// by Brendan Bellina, Nov 2009
// Some useful generic string functions
// Return string of sText repeated nCount times with optional string sDelimiter in between
string repeatString(string sText, int nCount = 1, string sDelimiter = "");
// Return string right justified to specified length. Returns entire string if length exceeds specified length.
string printStringRight(string sText, int nLength = 0, string sChar = " ");
// Return string of sText repeated nCount times with optional string sDelimiter in between
string repeatString(string sText, int nCount = 1, string sDelimiter = "")
{
string sOutput = "";
if (nCount < 1) return "";
int i;
for (i = 0; i < nCount; i++)
{
sOutput += sText;
if ( i < nCount - 1 && sDelimiter != "") sOutput += sDelimiter;
}
return sOutput;
}
// Return string right justified to specified length. Returns entire string if length exceeds specified length.
string printStringRight(string sText, int nLength = 0, string sChar = " ")
{
int nStringLength = GetStringLength(sText);
if (nStringLength >= nLength ) return sText;
return (repeatString(sChar, (nLength - nStringLength)) + sText);
}
// i_bb_it_partyreport_ac
// by Brendan Bellina
// Nov 2009
// Updated Jan 2010
// bb_it_partyreport OnActivate handler
// This script is executed automatically when the item is activated
// To trigger properly the name of the script MUST be "i_" + itemtag + "_ac"
// Also to make the item usable set Item Property to Cast Spell: Unique Power on Self
// Generates a state of the party report.
#include "ginc_debug"
#include "ginc_bb_stringlib"
// Determine if object is a player created PC (other than the main PC)
// Standard companions and associates will have tags but player created PC's will not.
// The main PC will be in the faction but not be in the roster, and will not have a tag.
// by Brendan Bellina, Jan 2010
int GetIsPlayerCreatedPC(object oPC=OBJECT_SELF);
void ReportOut(object oPC, string sOut)
{
PrettyDebug (sOut);
SendMessageToPC(oPC, sOut);
}
// Determine if object is a player created PC (other than the main PC)
// Standard companions and associates will have tags but player created PC's will not.
// The main PC will be in the faction but not be in the roster, and will not have a tag.
// by Brendan Bellina, Jan 2010
int GetIsPlayerCreatedPC(object oPC)
{
return ( (GetTag(oPC) == "")
&& (GetIsPC(oPC) == FALSE)
&& (GetIsRosterMember(oPC) == TRUE) );
}
// Create a report on a party member from a PC
string ReportMemberState(object oPM, object oPC)
{
string sOut = "";
string sResponse;
string sName = GetName(oPM);
if (sName == "")
sOut += "Name: [None]" + " [tag: " + GetTag(oPM) + "]";
else
{
sOut += "Name: " + GetName(oPM) + " [tag: " + GetTag(oPM) + "]" + "\\n";
// Is Player Created?
sResponse = (GetIsPlayerCreatedPC(oPM)==TRUE)?"Y":"N";
sOut += "Player Created PC: " + sResponse + " : ";
// Is a PC?
sResponse = (GetIsPC(oPM)==TRUE)?"Y":"N";
sOut += "PC: " + sResponse + " : ";
// Is FirstPC?
sResponse = (GetFirstPC()==oPM)?"Y":"N";
sOut += "FirstPC: " + sResponse + " : ";
// Is in party?
sResponse = (GetFactionEqual(oPM,oPC)==TRUE)?"Y":"N";
sOut += "In party: " + sResponse + " : ";
// Is Faction Leader?
sResponse = (oPM == GetFactionLeader(oPC))?"Y":"N";
sOut += "Is faction leader: " + sResponse + " : ";
// Is Dead?
sResponse = (GetIsDead(oPM, TRUE)==TRUE)?"Y":"N";
sOut += "Dead: " + sResponse + " : ";
// Is Dying?
sResponse = ((GetIsDead(oPM, FALSE)==TRUE) && (GetIsDead(oPM, TRUE)==FALSE))?"Y":"N";
sOut += "Dying: " + sResponse + " : ";
// Is an associate?
sResponse = (GetAssociateType(oPM)!=ASSOCIATE_TYPE_NONE)?"Y":"N";
sOut += "Associate: " + sResponse + " : ";
// Is a henchman?
sResponse = (GetAssociateType(oPM)==ASSOCIATE_TYPE_HENCHMAN)?"Y":"N";
sOut += "Henchman: " + sResponse + " : ";
// Is an animal companion?
sResponse = (GetAssociateType(oPM)==ASSOCIATE_TYPE_ANIMALCOMPANION)?"Y":"N";
sOut += "Animal Companion: " + sResponse + " : ";
// Is a familiar?
sResponse = (GetAssociateType(oPM)==ASSOCIATE_TYPE_FAMILIAR)?"Y":"N";
sOut += "Familiar: " + sResponse + " : ";
// Is summoned (excludes familiars and animal companions)?
sResponse = (GetAssociateType(oPM)==ASSOCIATE_TYPE_SUMMONED)?"Y":"N";
sOut += "Summoned: " + sResponse + " : ";
// Is dominated?
sResponse = (GetAssociateType(oPM)==ASSOCIATE_TYPE_DOMINATED)?"Y":"N";
sOut += "Dominated: " + sResponse + " : ";
// Is in conversation?
sResponse = (IsInConversation(oPM)==TRUE)?"Y":"N";
sOut += "Conversing: " + sResponse + " : ";
// Is in current area?
sResponse = (GetArea(oPM) == GetArea(oPC))?"Y":"N";
sOut += "In this area: " + sResponse + " : ";
// Is Roster Member?
sResponse = (GetIsRosterMember(oPM)==TRUE)?"Y":"N";
sOut += "Roster Member: " + sResponse + " : ";
// Is Available Roster Member?
sResponse = (GetIsRosterMemberAvailable(GetRosterNameFromObject(oPM))==TRUE)?"Y":"N";
sOut += "Available: " + sResponse + " : ";
// Is Selectable Roster Member?
sResponse = (GetIsRosterMemberSelectable(GetRosterNameFromObject(oPM))==TRUE)?"Y":"N";
sOut += "Selectable: " + sResponse + " : ";
// Is Roster Member Campaign NPC?
sResponse = (GetIsRosterMemberCampaignNPC(GetRosterNameFromObject(oPM))==TRUE)?"Y":"N";
sOut += "Campaign NPC: " + sResponse + " : ";
// Distance from Activator?
sResponse = FloatToString(GetDistanceBetween(oPM, oPC));
sOut += "Distance away: " + sResponse;
}
return sOut;
}
void GeneratePartyReport(object oPC)
{
ReportOut (oPC, "State of the Party Report");
ReportOut (oPC, " Current area: " + GetTag(GetArea(oPC)) );
ReportOut (oPC, "All Faction members:");
int bPCsOnly = FALSE; // set to TRUE for listing PCs only
object oFM = GetFirstFactionMember( oPC, bPCsOnly );
while (GetIsObjectValid(oFM))
{
ReportOut (oPC, ReportMemberState(oFM, oPC));
oFM = GetNextFactionMember( oPC, bPCsOnly );
}
ReportOut (oPC, "Roster members: (current NPC party limit " + IntToString(GetRosterNPCPartyLimit()) + ")" );
string sRosterName = GetFirstRosterMember();
while (sRosterName != "")
{
ReportOut (oPC, ReportMemberState( GetObjectFromRosterName( sRosterName ), oPC ) );
sRosterName = GetNextRosterMember();
}
}
void main()
{
//PrettyDebug("i_bb_it_partyreport_ac: Party Report");
// object oPC = (GetPCSpeaker()==OBJECT_INVALID?OBJECT_SELF:GetPCSpeaker());
object oPC = GetItemActivator();
// object oItem = GetItemActivated();
GeneratePartyReport( oPC );
}
Regards
#4
Posté 08 décembre 2010 - 02:07
DannJ wrote...
SoZ introduced the ability to import (and later export) your own custom party (shamelessly copying Icewind Dale II),
This is some light-hearted humor, right? I mean, I don't want to read too much into an innocent, flippant remark.
I would hope you are aware that custom parties are not unique to Icewind Dale II, and have a long history as a convention in computer role-playing games, especially Dungeons & Dragons computer role-playing games.
Harumph!
#5
Posté 08 décembre 2010 - 06:09
Dorateen wrote...
DannJ wrote...
SoZ introduced the ability to import (and later export) your own custom party (shamelessly copying Icewind Dale II),
This is some light-hearted humor, right? I mean, I don't want to read too much into an innocent, flippant remark.
I would hope you are aware that custom parties are not unique to Icewind Dale II, and have a long history as a convention in computer role-playing games, especially Dungeons & Dragons computer role-playing games.
Harumph!
Perhaps he meant the ability to name/describe a party and import/export it as a unit, as opposed to creating/importing/exporting individuals?
#6
Posté 08 décembre 2010 - 11:16
Also, with GetIsOwnedByPlayer, would that get only the original PC and other player created party members, but not companions/cohorts?
#7
Posté 09 décembre 2010 - 01:08
Dorateen wrote...
DannJ wrote...
SoZ introduced the ability to import (and later export) your own custom party (shamelessly copying Icewind Dale II),
This is some light-hearted humor, right? I mean, I don't want to read too much into an innocent, flippant remark.
I believe IWD2 was the first 'Forgotten Realms' D&D-based computer game to use it, so it was hardly innovative for it to appear in NWN2: SoZ.
It was one of the things I liked best about IWD2 (that, and 'heart of fury' mode). The dwarf voice set was also quite amusing; if you re-ordered your IWD2 party so a dwarven character was made leader, he would say something like "Oh, that's right. When things go badly, put the dwarf up front!". That was another great thing about the IWD2 party system - you could nominate different party members as leader at different times, rather than being stuck with the same leader for the whole game.
#8
Posté 09 décembre 2010 - 03:45
(note, I haven't tested any of this)
1. returns TRUE for any Companion/Cohort that is currently controlled
int GetIsPC(object oCreature);
// * Returns TRUE if oCreature is a Player Controlled character.
// NOTE: If the passed in creature is owned by the player, but the player is
// currently controlling another creature, this will return FALSE
// To check for ownership, see GetIsOwnedByPlayer()
2. returns TRUE only if the original PC is currently controlled
(might return TRUE for the original PC controlled or not!)
(Will this return TRUE if oCreature is not currently controlled
and *not* the original PC, but is still a member of PC's faction?
I suspect it does.)
int GetIsOwnedByPlayer( object oCreature );
// Description: Checks to see if this creature is owned by a player
// Returns: TRUE if oCreature is owned by a player.
// Note that if this creature is being controlled by the player, but is
// not the player's original "owned" character, this will return
// FALSE. You can check for control with GetIsPC()
3. returns TRUE iff original PC, or is created with SoZ party creator
int GetIsPlayerCreated( object oCreature );
// Characters created through the party creation mechanics
// are stored in the Roster system but are flagged as
// PlayerCreated to distinguish them from normal Roster
// contained NPCs. Note that if the character is not
// in the roster /at all/, this function returns false.
// This script function can query that flag.
// oCreature - object id of a creature to check
4. returns TRUE if created with SoZ party creator, or is regular Companion/Cohort
int GetIsRosterMember( object oMember );
//This returns true if the object passed in is in fact a roster member.
//If they are a roster member, then they exist within the roster table
5. returns !OBJECT_INVALID iff oAssociate (OBJECT_SELF) is an Associate (Henchman), Familiar, Summons, or Dominated-being
object GetMaster(object oAssociate=OBJECT_SELF);
// Get the master of oAssociate.
6. returns TRUE iff it's a possessed familiar, doh!
int GetIsPossessedFamiliar(object oCreature);
// This will return TRUE if the creature running the script is a familiar currently
// possessed by his master.
// returns FALSE if not or if the creature object is invalid
7. returns TRUE if it's a member of the PC-party or GetMaster() returns a member of the PC-party
int GetFactionEqual(object oFirstObject, object oSecondObject=OBJECT_SELF);
// * Returns TRUE if the Faction Ids of the two objects are the same
If Kaldor (et al.) wants to jump in with some Yes/Noes that'd be very welcome.
(nb. iff == if and only if)
#9
Posté 09 décembre 2010 - 04:01
Orion7486 wrote...
Thanks, for the clarification. So, if I understand correctly, the player can be in control of only 1 member at a time. So, GetIsPC would return true if the currently clicked on creature would be the original PC, a player created party member, or a companion/cohort?
Also, with GetIsOwnedByPlayer, would that get only the original PC and other player created party members, but not companions/cohorts?
GetIsPC(oPC) returns true if oPC is a player object. That means either the FirstPC in a single-player game or each of the player PC's in a multi-player game. It will not return true for anyone else in the party. I tried executing my script from a controller companion and the companion still showed false for GetIsPC, so I do not think controlling makes a difference.
GetIsOwnedByPlayer appears to only be true for the player objects also. It is not true for companions or player-created party members, or cohorts, or associates.
Player objects (the main PC for each player) are not in the roster. They are in the faction though.
Regards
Modifié par Kaldor Silverwand, 09 décembre 2010 - 04:07 .
#10
Posté 09 décembre 2010 - 06:33
hm, you got me to sit on my b*tt and make some tests:Kaldor Silverwand wrote...
GetIsPC(oPC) returns true if oPC is a player object. That means either the FirstPC in a single-player game or each of the player PC's in a multi-player game. It will not return true for anyone else in the party. I tried executing my script from a controller companion and the companion still showed false for GetIsPC, so I do not think controlling makes a difference.
I used a crate with a simple damage effect with the conditional
if (GetIsPC)and it gave the damage whether I was controlling the PC or Companion. When I used
if (GetIsOwnedByPlayer)however, you're right it was only the actual PC that took damage.
Then I hooked up a
whileloop that ran through the faction, and
if (GetIsOwnedByPlayer)gave damage only to the PC, whether or not it was controlled; but
if (GetIsPC)gives damage to only the controlled character - PC or companion.
go figur
So if I had to revise #1 (above) it would be, returns TRUE for any PC/Companion/Cohort that is currently controlled (not sure about "player-created party members", though it should be the same). And #2 would be, returns TRUE for the original PC, controlled or not (again, not sure about player-created party members, though my guess is it hits each one but not regular Companions/Cohorts). So, to get to the moral, if you want to check for any in the PC-party, use
GetFactionEqual()- which should catch Associates, Summons, Familiars, etc. also
And if ya want to eliminate those hangers-on, ya'll got to get creative with something like
if (GetIsPlayerCreated(oPC) || GetIsRosterMember(oPC))or
if (GetFactionEqual(oTarget, oPC) && (GetMaster(oTarget) == OBJECT_INVALID))
man, this is cuttin' into my gaming time
#11
Posté 09 décembre 2010 - 01:17
BG1 or BG2 allowed you to do your full party, or to play 1 char and get cohort found in game to come with you. they gave you the choice, like many other games, TOEE for exemple.
That SOZ feature is actually a return to the "roots" that were shamelessly forgoten where player did have the choice to make their own party or to have NPC join them.
#12
Posté 09 décembre 2010 - 02:17
DannJ wrote...
Dorateen wrote...
DannJ wrote...
SoZ introduced the ability to import (and later export) your own custom party (shamelessly copying Icewind Dale II),
This is some light-hearted humor, right? I mean, I don't want to read too much into an innocent, flippant remark.
I believe IWD2 was the first 'Forgotten Realms' D&D-based computer game to use it, so it was hardly innovative for it to appear in NWN2: SoZ.
Hey, I love IWD2 also (and of course the original Icewind dale) so we are on the same page, here.
I just want to clarify, the Forgotten Realms series of Dungeons & Dragons based computer role-playing games really started with the SSI Gold box game Pool of Radiance. There was a full four title release set around the Dalelands and Moonsea region, plus two more games set in the Savage Frontier.
Then there was the Eye of the Beholder trilogy set in Waterdeep and Myth Drannor.
These are all from the early to mid 1990's and predate the Infinity Engine and the latter Storm of Zehir.
The language of "shamelessly copied" just confused me a little. Obviously, what Obsidian did was going back to the roots of Old School cRPG (much to the chagrin of its many detractors) and this ought to be applauded.
Thanks for the reply!
Modifié par Dorateen, 09 décembre 2010 - 02:19 .
#13
Posté 09 décembre 2010 - 10:51
Some functions I missed the first time 'round (just trying to make a list of all the ways to 'grab' a PC or ally):
(nb. SP-easy, MP gets complicated)
8. returns original PC or currently controlled object (depending on switch)
object GetFirstPC(int bOwnedCharacter=TRUE);
// Get the first PC in the player list.
// This resets the position in the player list for GetNextPC().
//bOwnedCharacter, if true, returns the first player's owned PC
//object. If false, returns the first player's currently controlled
//object.
9. .. not sure if bPCOnly switch includes Companions/Cohorts
object GetFirstFactionMember(object oMemberOfFaction, int bPCOnly=TRUE);
// Get the first member of oMemberOfFaction's faction (start to cycle through
// oMemberOfFaction's faction).
// * Returns OBJECT_INVALID if oMemberOfFaction's faction is invalid.
10. .. note, returns a string; should not include PCs, only Companions/Cohorts
string GetFirstRosterMember();
//This gets the first roster member in the list. Roster members are
//sorted by the order that they were added to the roster.
//It is to be coupled with GetNextRosterMember() if one needs to
//iterate over the roster
//Returns an empty string if there are no roster members
//The string return value is the roster name of the first roster member.
these of course, should be used with
GetNext...to iterate through characters.
& don't forget
GetIsFriend()
GetIsEnemy()
GetIsNeutral()
GetIsReactionTypeFriendly()
GetIsReactionTypeHostile()
GetIsReactionTypeNeutral()
and, of course
GetIsDM()
GetIsDMPossessed()
.. resume program.
#14
Posté 09 décembre 2010 - 11:57
Well, based on how I understand the function comments, it seems that your observations would be correct, ie. GetISPC comes back true for original PC, player created party member, or companion, and only if it is the currently clicked on character;; and GetIsOwnedByPlayer comes back true only for a player created character, such as original PC and player created party member, not companions.kevL wrote...
So if I had to revise #1 (above) it would be, returns TRUE for any PC/Companion/Cohort that is currently controlled (not sure about "player-created party members", though it should be the same). And #2 would be, returns TRUE for the original PC, controlled or not (again, not sure about player-created party members, though my guess is it hits each one but not regular Companions/Cohorts). So, to get to the moral, if you want to check for any in the PC-party, useGetFactionEqual()- which should catch Associates, Summons, Familiars, etc. also
But, Kaldor came up with basically the opposite, and he seems to know what he's about on these boards, so I'm still a tad confused...I think.
#15
Posté 11 décembre 2010 - 05:02
Regards
#16
Posté 11 décembre 2010 - 06:20
#18
Posté 12 mars 2013 - 12:26
Regards
#19
Posté 12 mars 2013 - 01:13
btw at the bottom of the script you'll find a function that i believe returns the OwnedPC (truePC, realPC, mainPC, whatver) *no matter what PC-faction creature is passed in*
at least in SP (single-player). I imagine you'll want to run the script through some tests before trusting it for MP, but it should be good other than that function, which I think in MP returns the OwnedPC of the faction leader (if a Roster-like object is passed in) but the OwnedPC itself if that is passed in. It can be corrected further by commenting out one of the Else clauses. I guess it could be handy for writing journal entries/ local_vars, eg. on a consistent character etc.





Retour en haut






