Hiring Companions for a duration
#1
Posté 18 novembre 2011 - 10:01
Thanks!:happy:
#2
Posté 19 novembre 2011 - 03:54
hire hench on GetTimeHour()
release hench on GetTime Hour() +1
#3
Posté 19 novembre 2011 - 04:08
My first suggestion would be to think about using DelayCommand to call your hire-or-release script in an hour (probably not while in combat--eep!). I don't know if DelayCommand will work if the player leaves and re-joins the server, however...will the countdown resume when they rejoin?
You could also start a timer with NWNX, which is generally a reliable way to go about things. Again, I don't know what happens if a PC leaves and rejoins.
Of course, you could also run a heartbeat on the NPC. This would certainly work whenever the PC and NPC are present, but a lot of PCs with a lot of henchmen all running extra checks in their heartbeats might be a performance hit (though I'd imagine it would be relatively minor).
Pain could probably tell you. He's done tons of PW scripting.
#4
Posté 19 novembre 2011 - 06:00
#5
Posté 19 novembre 2011 - 07:12
Shallina wrote...
I'd use Morbane approach.
Morbane's approach just gets the time. That's fine, but what event would you call it from? Heartbeat of the module, hench, etc.?
#6
Posté 19 novembre 2011 - 10:26
Hench heartbeat. It will make the scripting of things like detecting if the hench is in combat much simpler. Performance won't be a problem either since the henchies are already running heartbeats anyway.MasterChanger wrote...
Shallina wrote...
I'd use Morbane approach.
Morbane's approach just gets the time. That's fine, but what event would you call it from? Heartbeat of the module, hench, etc.?
#7
Posté 19 novembre 2011 - 11:26
On each heartbeat (6 secs) add one and then test its value. If it is less than 600 then continue, if it is greater than 600 but not in combat then start the convo. That makes it independant of the actual time and I think Lilac soul could write that one for you.
PJ
Modifié par PJ156, 19 novembre 2011 - 11:27 .
#8
Posté 19 novembre 2011 - 11:36
#9
Posté 19 novembre 2011 - 11:36
On every heartbeat, the script checks to see if the henchmen is a temp hire (your boolean), and then adds one to your counter. If the counter is greater than the term of service, the script orders the henchmen to start a conversation with the PC. If either the henchmen or the PC are in combat, the conversation fails to fire and the script will try again on the next heartbeat. You might even want to keep track of the extra rounds, so the henchmen can demand a bonus before signing on again.
#10
Posté 20 novembre 2011 - 09:26
So in order to have something working all the time, you need to store a value and check it, and compare so even if the script is interupted, when it will start again it should start from where it was stoped.
#11
Posté 20 novembre 2011 - 10:47
#12
Posté 21 novembre 2011 - 02:14
#13
Posté 21 novembre 2011 - 10:25
If you have having a number of henchmen it might make sense to add to the module heartbeat and cycle through the henchmen oppose to having each henchman fire off their script.
A few people have also mentioned checking if the PC and henchman are in combat, you may also want to check if the PC is already in a conversation.
I like the idea of counting the rounds that a the NPC & PC are busy. It would make sense that a hired sword may ask for more gold if their time ran out right before an epic battle.
#14
Posté 12 décembre 2011 - 12:29
I've started with a generic script to test things out, and I figure I'll customize it a bit more to each henchmen as I go. Right now, it works like this: PC speaks to NPC and can hire Henchman. Upon hire, Henchman spawns next to PC and I've attached all the default Companion scripts to the Henchman. I've added to the default gb_comp_heart script (heartbeat script) the following line:
ExecuteScript("psy_hench_hb1", OBJECT_SELF);
I've tried two different versions of psy_hench_hb1, but neither of them seem to work. The first was this:
int nInt;
/* Script generated by
Lilac Soul's NWN Script Generator, v. 2.3
For download info, please visit:
http://nwvault.ign.c...&id=4683&id=625 */
//Goes on creature's OnHeartbeat. Fires when not fighting or talking.
void main()
{
object oPC = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC, OBJECT_SELF, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN);
if (IsInConversation(OBJECT_SELF) || GetIsInCombat()) return;
if (GetLocalInt(oPC, "hench_timer")< 10)
{
nInt = GetLocalInt(oPC, "hench_timer");
nInt += 1;
SetLocalInt(oPC, "hench_timer", nInt);
}
if (GetLocalInt(oPC, "hench_timer")>= 10)
{
ActionStartConversation(oPC, "cnv_hench_rehire");
}
}
For the second attempt, I included setting the initial integer with the hiring conversation (hench_timer set to 1), added a second script to execute (psy_hench_hb2, along with psy_hench_hb1 in the default heartbeat script) and then tried this:
psy_hench_hb1:
/* Script generated by
Lilac Soul's NWN Script Generator, v. 2.3
For download info, please visit:
http://nwvault.ign.c...&id=4683&id=625 */
//Goes on creature's OnHeartbeat. Fires when not fighting or talking.
void main()
{
object oPC = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC, OBJECT_SELF, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN);
if (IsInConversation(OBJECT_SELF) || GetIsInCombat()) return;
int nInt;
nInt = GetLocalInt(oPC, "hench_timer");
nInt += 1;
SetLocalInt(oPC, "hench_timer", nInt);
}
psy_hench_hb2:
/* Script generated by
Lilac Soul's NWN Script Generator, v. 2.3
For download info, please visit:
http://nwvault.ign.c...&id=4683&id=625 */
//Goes on creature's OnHeartbeat. Fires when not fighting or talking.
void main()
{
object oPC = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC, OBJECT_SELF, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN);
if (IsInConversation(OBJECT_SELF) || GetIsInCombat()) return;
if (GetLocalInt(oPC, "hench_timer")< 5)
return;
ActionStartConversation(oPC, "cnv_hench_rehire");
}
Oddly, with the first attempt, if I hired a second henchman along with the first, the rehire conversation would pop up (both would fire simultaneously, which I assume is the result of setting only a single variable that they both operated off of). Yet, if I have only a single henchman hired, no matter how long I wait (up to five minutes), the rehire conversation does not fire. Any thoughts or insight?
#15
Posté 12 décembre 2011 - 01:51
So, first, for a test (Just a test, Pain) replace that function with GetFirstPC(). Once that works, set the PC as a local object on the henchman, maybe from the conversation that hires the henchman. Also, I would keep the int on the henchman themself, so you can easily have multiple henchmen with different terms of service.
#16
Posté 14 décembre 2011 - 02:55
#17
Posté 14 décembre 2011 - 01:42
#18
Posté 14 décembre 2011 - 09:44
Making a heartbeat counter on the henchman based on the 6 second cycle might be more effective and you would need to have multiple functions available for different time intervals.
pseudo code:
object oHench = OBJECT_SELF;
object oPC = GetMaster() //requires an #include but no toolset at the moment
int nTime = GetLocalInt(oHench);
SetLocalInt(oHench, nTime)
if(GetLocalInt(oHench) > nTime * hours or minutes or days e.g. 10 = minute / 86400 = day
do something - convo or action
that is the basic idea and not such a bad place to start. if I can get onto my game pc I will do some testing and experimenting.
good luck
Modifié par Morbane, 14 décembre 2011 - 09:47 .
#19
Posté 14 décembre 2011 - 10:42
//On Module Heartbeat script
#include "ginc_time"
void main()
{
struct CHoursPassed rHP = CheckTime();
int nNumModuleHoursPassed = rHP.nNumModuleHoursPassed;
int nNumCampaignHoursPassed = rHP.nNumCampaignHoursPassed;
if ((nNumModuleHoursPassed > 0) ||
(nNumCampaignHoursPassed > 0))
{
UpdateClockForAllPlayers();
}
}
Perhaps you could set a local variable on the henchman using the nNumModuleHoursPassed / nNumCampaignHoursPassed structure value when hired, then give them a custom HB script that constantly checks whether the hours passed has surpassed their hire time (before running the default henchman HB at the end of the script). The first few warnings could just fire some floating text warning of the time limit approaching, eventually resulting in a conversation (if not in combat) that forces the matter once the deadline has gone past by more than a few hours.
#20
Posté 15 décembre 2011 - 09:22
DannJ wrote...
The module heartbeat script that updated the MotB date/time GUI on the toolbar has the following code:
//On Module Heartbeat script
#include "ginc_time"
void main()
{
struct CHoursPassed rHP = CheckTime();
int nNumModuleHoursPassed = rHP.nNumModuleHoursPassed;
int nNumCampaignHoursPassed = rHP.nNumCampaignHoursPassed;
if ((nNumModuleHoursPassed > 0) ||
(nNumCampaignHoursPassed > 0))
{
UpdateClockForAllPlayers();
}
}
.
The nNumModuleHoursPassed / nNumCampaignHoursPassed structure value is interesting - it returns the whole numnber of hours that have passed since the last time the function returned a non-zero value. It returns zero for the first 19 rounds, then 1 for the 20th, then returns back to zero. If you advance the time by a certain number of hours, then the next round it returns that value (so sleep for 8 hours, it returns an 8).
The following companion heartbeat script uses the function (some assembly required). It assumes a normal module. If you're using a campaign module, then use rHP.nNumCampaignHoursPassed instead.
--
// gb_comp_hired_heart
// Hearbeat script for companion hired by the hour
// Set local variables on companion: HoursPayedFor (int) and Conversation (string)
#include "ginc_time"
void main()
{
struct CHoursPassed rHP = CheckTime();
int nNumModuleHoursPassed = rHP.nNumModuleHoursPassed;
int iHoursPayedFor = GetLocalInt(OBJECT_SELF, "HoursPayedFor");
int iHoursElapsed = GetLocalInt(OBJECT_SELF, "HoursElapsed");
if ( nNumModuleHoursPassed > 1)
{
iHoursElapsed = iHoursElapsed + nNumModuleHoursPassed;
SetLocalInt(OBJECT_SELF, "HoursElapsed", iHoursElapsed);
}
if (iHoursElapsed >= iHoursPayedFor)
{
// Check if in combat, or PC incapacitated or in conversation with someone else. If not...
string sConv = GetLocalString(OBJECT_SELF, "Conversation");
AssignCommand(GetFirstPC(), ActionStartConversation(OBJECT_SELF,sConv, FALSE, FALSE, TRUE, FALSE));
}
ExecuteScript("gb_comp_heart", OBJECT_SELF);
}
Modifié par DannJ, 15 décembre 2011 - 10:19 .





Retour en haut






