Advancing the state of commoner AI
#51
Posté 27 juillet 2011 - 11:59
DannJ: What you talk about in Gothic 3 is basically what's in the PRR system for NWN2.
#52
Posté 29 juillet 2011 - 02:44
The mechanism needs to be dressed up.
#53
Posté 29 juillet 2011 - 09:55
nicethugbert wrote...
I find it weird that people can get caught steeling, etc., and that's the end of it. It is more realistic if the event colors the rest of your interactions. For instance, some people refuse to talk to you, others are unfriendly, afraid, etc. You can only shop, or even enter, certain parts of town. You get a nick name or some other reference. You burn up favors. The people who will deal with you, will exploit the fact that you now have limited options, etc. You escape the executioner by joining the Grey Wardens .........
The mechanism needs to be dressed up.
It might be enjoyable to create a rogues-only module. It would consist of all thief-like, skills-based quests where combat and magic are secondary; you win primarily by sneaking around and performing various skull-duggery or social engineering--taking on the tasks directly would be heavily-biased toward lethality. Your recruitable companions would be various unsavory types (at least superficially), but it could build into a Robin Hood-like scenario based in a city. Maybe you're trying to take down a thieves guild that had your parents killed, for example. I think that would be a good type of adventure to implement a thievery-response framework.
#54
Posté 29 juillet 2011 - 11:10
Yeah, who ever heard of a module like that.rjshae wrote...
nicethugbert wrote...
I find it weird that people can get caught steeling, etc., and that's the end of it. It is more realistic if the event colors the rest of your interactions. For instance, some people refuse to talk to you, others are unfriendly, afraid, etc. You can only shop, or even enter, certain parts of town. You get a nick name or some other reference. You burn up favors. The people who will deal with you, will exploit the fact that you now have limited options, etc. You escape the executioner by joining the Grey Wardens .........
The mechanism needs to be dressed up.
It might be enjoyable to create a rogues-only module. It would consist of all thief-like, skills-based quests where combat and magic are secondary; you win primarily by sneaking around and performing various skull-duggery or social engineering--taking on the tasks directly would be heavily-biased toward lethality.
#55
Posté 22 octobre 2011 - 01:52
social.bioware.com/forum/1/topic/159/index/8554242
Go to his youtube channel and watch the videos.
#56
Posté 22 octobre 2011 - 01:41
As hardware gets better, builders can start populating their villages and towns with more and more npcs, and they'll need something to help them manage those ambient masses. The Legends AI, as far as I could tell, just sets NPC's up with generic mobile or immobile ambient animations, not the variety of occupations you were talking about. (Their system is indeed impressive, but meant for a massive-but-sparse PW, not a detailed single-player mod).
#57
Posté 22 octobre 2011 - 02:44
I posted in his thread suggesting the possibility of adding the actions built into this system into his as action options other than the 4 or so in his current system. The approach I took and the one he's using are pretty similar, control things via wp instead of on the creature. His GUI plugin for setting behavior is a massive improvement in ease of use.Lugaid of the Red Stripes wrote...
You're not giving up on your project, are you? I just watching the first two videos on the Legends AI, but it seems not to have the same level of detail you were envisioning for your project.
As hardware gets better, builders can start populating their villages and towns with more and more npcs, and they'll need something to help them manage those ambient masses. The Legends AI, as far as I could tell, just sets NPC's up with generic mobile or immobile ambient animations, not the variety of occupations you were talking about. (Their system is indeed impressive, but meant for a massive-but-sparse PW, not a detailed single-player mod).
I watched all the videos and there's only a few general things I was proposing that he didn't already do. His npc's sleep by just sleeping on the ground or at designated wp, they aren't able to find a door and dissapear for the night to simulate going home for the evening. His npc's only differentiate day/night, not the 6 periods mine tries to do. I have a wider variety of actions, but he already has actions so it would just be expanding the action options offered. I'd also love to see the prr reputation system (as an optional checkbox) and the csl ai (standard because of it's massive ai speed boost) integrated into all that.
In the demo he is spawning predefined npc's, so things would look the same every day. I'm already using APEP's dynamic npc's. link. Apep's npc system has npc's that can dynamically dress, get voicesets, get names etc when they spawn. You just place them, or spawn them, and they do the rest. You can make an npc who for example walked a set of waypoints, but that npc would dress differently every spawn.
Add support for all that and it would be a "perfect" system. I see Marshall, the Legends AI author on IRC fairly regularly. So I'll have to catch him next time he's on.
I've been busy working on other things and not this for the past few months. Scripting is not something I am fond of and something like this is a polish thing that can be added while otherwise testing.
Modifié par kamal_, 22 octobre 2011 - 03:06 .
#58
Posté 23 décembre 2011 - 04:11
#59
Posté 31 décembre 2011 - 03:31
Npc's now correctly go to the action waypoint they pick and carry out their actions at their selected times. There's still some bugs with equipping items for jobs ("woodsmen" should generate and equip axes for instance) and moving to sleep waypoints (if an npc decides to sleep, it lays down on the spot instead of moving to a sleep waypoint). Also I need to set things up so the numbers assigned to the time ipoints are just overall percentages and not a set of straight percentage chances (right now a 50,50 would mean 1/2 the npc's would pick the first activity, and half the remaining would pick the second, instead of 1/2 the first, and 1/2 the second).
#60
Posté 31 décembre 2011 - 04:29
Basically, you have a function that adds the activity (represented by a string, index number, whatever) to an existing pseudo-array, and increments the number of array items (N). Then you just need to use Random(N) to pick one of the elements out of the pseudo-array. You can give a particular activity more weight by adding it more than once to the array.
#61
Posté 26 mars 2012 - 01:47
Anyway, solved three large bugs this weekend:
Npc was not correctly starting their action.
Incorrect determination of time period during the "sleep" period, causing the npc to change what they thought the time period was every heartbeat.
Npc would not correctly change their wielded item when switching between two activities that both required an equipped item (eg playing lute with the handaxe used when chopping wood the previous period).
Also fixed: npcs properly detect the activity time if you skip a time
period, for instance if you advanced the time 8 hours on rest.
Previously you could not skip a time period. This was fixed as part of
fixing the sleep period bug above.
There are still a lot of things to fix/improve, like the activity chance thing I mentioned a few posts prior. But with these fixes the completion percentage has advanced significantly, enough to make a post worthwhile.
Modifié par kamal_, 26 mars 2012 - 10:47 .
#62
Posté 26 mars 2012 - 01:54
There still seem to be some problems making sure they move to the right waypoints though.
600x300http://dl.dropbox.com/u/3879894/NWN2_SS_032612_185700.jpg[/img]
Modifié par kamal_, 26 mars 2012 - 11:08 .
#63
Posté 29 mars 2012 - 01:05
How about the following, which allows you to do things as a series of if/else statements. That makes things more understandable for the non-advanced scripter than doing pseudo arrays. I'm unsure if the math for the middle case works out correctly, I think it does.Lugaid of the Red Stripes wrote...
I've solved you're second issue using a pseudo array, for example in my ambient chat scripts in The Danaan Unvanquished.
Basically, you have a function that adds the activity (represented by a string, index number, whatever) to an existing pseudo-array, and increments the number of array items (N). Then you just need to use Random(N) to pick one of the elements out of the pseudo-array. You can give a particular activity more weight by adding it more than once to the array.
int nPercentChance =0; //anticpatory testing. not currently used. kamal
//how this works, the nPercentChance is added to in the amount of the localInt for the activity for the ip_ object for that time.
//so for a 30 on the local int for NPCHidden for ip_sleep1
//the first check is the if d100 < ((30/100-nPercentChance)*100) to see if NPCHidden should be the activity.
//in this case d100 <30/100, same as a straight d100 chance
//if the if statement is false, nPercentChance has the amount of the local int for the activity added to it.
// in this example, it will be 0 + 30 = 30
// then NPCAgree int of 50
/* we've already accounted for 30%, there is 70% remaining. Which means for the chance for NPCAgree we need have a 50/100-nPercentChance chance, or 50/((100-30)*100) or 50/70
if that is false, add the local int for NPCAgree to nPercentChance (30 [from NPCHidden]+50 in this example
nPercentChance is now 80.
then NPCAngry int of 20
since there's only 20% remaining, we have a 20/100-nPercentChance chance, 100% since it's 20/((100-80)*100) or 20/20
*
//example
/*
if ((d100())< (GetLocalInt(GetObjectByTag("ip_sleepl"),"NpcHidden"))/((100-nPercentChance)*100))
{
}
else
{
nPercentChance = nPercentChance +(GetLocalInt(GetObjectByTag("ip_sleepl"),"NpcHidden"));
}
*/
Modifié par kamal_, 31 mars 2012 - 06:19 .
#64
Posté 29 mars 2012 - 03:37
// chat_amb_bayaka
/*
Description: Chatbot script for ambient conversations/barkstrings
<CUSTOM7101> - Greeting
int iNumStructs - Number of currently valid structs
string sStructX - pseudo-array of currently valid structs
*/
// Name_Date
//These functions at the top handle the pseudo-array, 'Struct' is my shorthand for dialog that is constructed by a script.
//add sNPCLine as a valid struct
void AddStruct(string sNPCLine) {
int iNumStructs = GetLocalInt(OBJECT_SELF, "iNumStructs") + 1;
SetLocalString(OBJECT_SELF, "sStruct" + IntToString(iNumStructs), sNPCLine);
SetLocalInt(OBJECT_SELF, "iNumStructs", iNumStructs);
}
//clears all structs
void ClearAllStructs() {
int iNumStructs = GetLocalInt(OBJECT_SELF, "iNumStructs");
while (iNumStructs > 0) {
SetLocalString(OBJECT_SELF, "sStruct" + IntToString(iNumStructs), "");
iNumStructs = iNumStructs - 1;
}
SetLocalInt(OBJECT_SELF, "iNumStructs", 0);
}
//builds token for NPCLine
void BuildNPCLine() {
int iNumStructs = GetLocalInt(OBJECT_SELF, "iNumStructs");
int iStruct = Random(iNumStructs) + 1;
SetCustomToken(7101, "Oops, I forgot my line!");
string sNPCLine = GetLocalString(OBJECT_SELF, "sStruct" + IntToString(iStruct));
SetCustomToken(7101, sNPCLine);
}
//These functions are just here to help the main script get at some important variables.
//calculates current ambient task - cribbed from ambienttasks
string sAmbientTask(int iHour) {
if (GetLocalInt(OBJECT_SELF, "iAmbient") != 1) {
return "idle";
}
int iScheduleType = GetLocalInt(OBJECT_SELF, "iScheduleType");
string sTask;
if (iScheduleType == 0) {
sTask = GetLocalString(OBJECT_SELF, "sTaskDay");
}
if (iScheduleType == 1) {
if ((iHour >= 6) && (iHour < 17)) {
sTask = GetLocalString(OBJECT_SELF, "sTaskDay");
}
else {
sTask = GetLocalString(OBJECT_SELF, "sTaskNight");
}
}
if (iScheduleType == 2) {
if ((iHour >= 6) && (iHour <= 16)) {
sTask = GetLocalString(OBJECT_SELF, "sTaskDay");
}
else if ((iHour >= 17) && (iHour <= 23)){
sTask = GetLocalString(OBJECT_SELF, "sTaskEvening");
}
else {
sTask = GetLocalString(OBJECT_SELF, "sTaskNight");
}
}
return sTask;
}
void main()
{
ClearAllStructs();
object oPC = GetFirstPC(); //Yes, this really should be GetPCSpeaker();
//First, we're gonna build a list of random items, by checking various things and giving the NPC an appropriate line or //two.
//This first section checks the area, and gives area-specific lines:
string sArea = GetTag(GetArea(OBJECT_SELF));
if (sArea == "defuskie") {
AddStruct("You gonna help me load the boat?");
AddStruct("I wish that dog would leave me alone!");
AddStruct("Cesuo zainar?");
}
if (sArea == "fortmoultrie") {
AddStruct("Why do the seagulls gotta be so noisy?");
//Here we have a nested journal entry check, to make things more specific
if (GetJournalEntry("quest_trompement", oPC) == 20) {
AddStruct("Chu Si'leh's down on the beach, countin' coffins.");
}
if (GetJournalEntry("quest_collateral", oPC) == 1) {
AddStruct("You wanna talk to Typ Sutpen, he's getting sloshed in his shack.");
}
}
if (sArea == "wassau") {
AddStruct("Chou Doufu! You smell like a bumpkin!");
AddStruct("Imp, Gendarmie, ERA, they all look alike to me!");
if (GetJournalEntry("quest_verbena", oPC) == 12) {
AddStruct("Cape Jessamine? Just head along the river to Ranzhuang, and cross at Harper's Ferry.");
}
}
if (sArea == "wassau_underground") {
AddStruct("Beware of Lord Mupwhump!");
AddStruct("Yeah, work is slow, no ships at the dock!");
AddStruct("I donna know, you just get used to it, I guess.");
AddStruct("Go buy a flare if you can't see the kobolds, don't come crying to me!");
}
if (sArea == "wassau_boilerroom") {
AddStruct("Yeah, Ke'kele is a hell of a drug...");
AddStruct("No, he just keeps going.");
AddStruct("Talk to the boss, Tiao Wu, I got work to do.");
}
if (sArea == "wassau_arsenal") {
AddStruct("Nobody knows, the trouble I see...");
AddStruct("Don't judge, a job's a job.");
AddStruct("No, I don't know why they look like that.");
}
if (sArea == "harpersferry") {
AddStruct("Go talk to Baoshu, he can set you up.");
if (GetJournalEntry("quest_verbena", oPC) == 12) {
AddStruct("Cape Jessamine? Just follow the River road North to Beaufort, and get Kharonge to row you across.");
}
}
if (sArea == "bayoualesienne_musgroveshaven") {
AddStruct("So you and Capt Reynolds fought in New Market together?");
}
if (sArea == "capejessamine") {
AddStruct("You seen any dog-heads around?");
AddStruct("Fletch? I wouldn't, but I ain't crazy like you.");
AddStruct("Yeah, go on and milk the cows, save us the trouble.");
AddStruct("At least they didn't get any lawn jockeys...");
if (GetJournalEntry("quest_verbena", oPC) == 12) {
AddStruct("Go talk to Ms. Desiree, I got work to do!");
}
int iHeavy = GetJournalEntry("quest_heavy", oPC);
if (iHeavy == 0) {
AddStruct("Don't listen to the cows, they're crazy!");
}
if ((iHeavy >= 1) && (iHeavy < 10)) {
AddStruct("They are badgers everywhere!");
AddStruct("Tian ah! What are doing with the cows!");
AddStruct("Aieee! Niumen jingpao !");
}
if (iHeavy >= 10) {
AddStruct("You have any idea why there's a badger cowering under my bed?");
AddStruct("What did you do to our cows?! They're all bloodied up like a bunch of dogheads!");
AddStruct("Wo jianle! Women niu da huande pigu!");
}
}
if (sArea == "capejessamine_barn") {
AddStruct("No, we don't do kobold fights, stop asking!");
if (GetJournalEntry("quest_sojourner", oPC) == 4) {
AddStruct("Spirit master? Ting bu dong...I don't know.");
}
}
if (sArea == "beaufort_tavern") {
AddStruct("Talk to the bartender, I'm busy!");
AddStruct("You'll just have to hold it, or go outside.");
AddStruct("Go talk to Ms. Amantha if ya got something to sell.");
if (GetJournalEntry("quest_verbena", oPC) == 12) {
AddStruct("Cape Jessamine? It's just across the river, go get Kharonge to row you across.");
}
}
if (sArea == "beaufort_meetinghouse") {
AddStruct("Talk, talk, talk! They drive me crazy!");
AddStruct("Did you have to track in so much mud?");
if (GetJournalEntry("quest_verbena", oPC) == 12) {
AddStruct("Cape Jessamine? It's just across the river, go get Kharonge to row you across.");
}
}
if (sArea == "beaufort_krupp") {
AddStruct("I don't know, I just work here.");
AddStruct("Talk to the dwarf if you need something.");
AddStruct("Yeah, I know, the smoke gets annoying.");
}
if (sArea == "ocmulgeecaverns") {
AddStruct("Slag, slag, slag! Slag all day, slag all night!");
AddStruct("Yeah, I was expecting a lot more critters down here, too.");
AddStruct("Viva la revolucion!");
AddStruct("I'm saving up my money for the ****fight tonight!");
}
if (sArea == "ocmulgeecaverns_depths") {
AddStruct("Come on, green baby, stick him in the cloaca!");
AddStruct("Wo ai ne, Hong Long!");
AddStruct("Fight! Fight!");
AddStruct("Come on, daddy needs a new pair of shoes!");
AddStruct("Stupid kobold! How am I supposed to explain this to my wife?");
AddStruct("Lu Long! Lu Long!");
AddStruct("Dammit, I've seen a more impressive kobold in my grandma's privy!");
AddStruct("I know, I know, the abandoned underground city just happened to have a ****fighting ring!");
AddStruct("Aren't you supposed to be somewhere doing something important?");
AddStruct("Can't you cast a spell or something? I'm 'bout to lose me shirt!");
AddStruct("Please, Dana'an! Do something! At least staunch that gash before he passes out!");
}
if (sArea == "beaufort") {
AddStruct("Can you get me a job at the Bagnio?");
AddStruct("Stay away from Kandoufu, he's a li'l touched in the head.");
AddStruct("The Imps can't attack us here, can they?");
if (GetJournalEntry("quest_verbena", oPC) == 12) {
AddStruct("Cape Jessamine? Talk to Kharonge at the dock, he can row you across.");
}
}
if (sArea == "ranzhuang") {
AddStruct("Was that a muckrat I saw?");
AddStruct("Nah, it never really washes out.");
AddStruct("Yeah it's weird, rain here all the time, but nowhere else...");
AddStruct("Bossman MacClaslin's up at Harper's Ferry.");
if (GetJournalEntry("quest_verbena", oPC) == 12) {
AddStruct("Cape Jessamine? Just cross at Harper's Ferry, and make your way North to Beaufort");
}
if (GetJournalEntry("quest_sojourner", oPC) == 10) {
AddStruct("The Sibyl's down South, near the big tree.");
}
}
//Now we're gonna check the time of day, and give time-specific lines
int iHour = GetTimeHour();
if ((iHour < 6) || (iHour > 18)) {//night
AddStruct("Shouldn't you be in bed?");
AddStruct("Night time is the right time...");
}
else if (iHour < 12) {//morning
AddStruct("I miss my bed...");
AddStruct("Kafei...Kafei...wo yao kafei...");
}
else if (iHour > 16) {//evening
AddStruct("Is it six o'clock yet?");
AddStruct("Whew, such a long day...");
}
else {//early afternoon
AddStruct("You eat lunch yet?");
AddStruct("It's so hot!");
AddStruct("Ni chi le ma?");
}
//Now the NPC's current ambient task:
string sTask = sAmbientTask(iHour);
if (sTask == "weed") {
AddStruct("Yeah, it's hard work, why don't you try it?");
AddStruct("I know, everyday the same row, same field, work never gets done!");
}
else if (sTask == "flute") {
AddStruct("Duibuqi, that's the only song I know.");
}
else if (sTask == "dance") {
AddStruct("Just like Tiao Wu, right?");
}
else if (sTask == "drink") {
AddStruct("**hic**");
AddStruct("Kambei!");
AddStruct("Honour to the spirit master!");
}
else if (sTask == "tend") {
AddStruct("I'm busy, go bother someone else!");
}
else if (sTask == "work") {
AddStruct("Whew, I'm tired!");
AddStruct("Ya know what? I kinda like beatin' on things.");
}
else if (sTask == "sweep") {
AddStruct("...of course I don't need a real broom, I'm just a gnome...");
}
else if (sTask == "sit") {
AddStruct("Have a rest!");
}
else if (sTask == "sitground") {
AddStruct("Yeah, I know, all the good seats were taken.");
if (sArea == "fortmoultrie") {
AddStruct("Yo heshui ma?");
AddStruct("Wode shenti meiyou qian, wode shenti maile!");
AddStruct("Cao ni ma, gaoren!");
AddStruct("Wode Zhongwen huaile, hai bu dui!");
}
}
else if (sTask == "mingle") {
AddStruct("Hey, I'm walking here!");
}
else if (sTask == "shovel") {
AddStruct("Maybe when the war is over, I'll get a real shovel...");
}
else if (sTask == "cook") {
AddStruct("Yeah, it needs more sugar.");
}
else if (sTask == "sleep") {
AddStruct("Can't a gnome nap in peace?");
}
else if (sTask == "follow") {
AddStruct("You chase monsters, but I gotta follow this thing around all day!");
}
//And now general plot-related stuff
//Plot-related
if (GetJournalEntry("quest_verbena", oPC) < 3) {
AddStruct("You need to go see Kalypso if you need some verbena.");
}
int iQuest = GetJournalEntry("quest_front", oPC);
if ((iQuest >= 1) && (iQuest < 10)) {
AddStruct("Is it true, they're stealing gnomes?");
AddStruct("I heard they were putting gnomes into tin cans!");
}
if (GetJournalEntry("quest_front", oPC) >= 10) {
AddStruct("How much you think gnavi gnomes get paid?");
AddStruct("How do the gnavi gnomes take a leak in those things?");
AddStruct("I wish I was a gnavi gnome...they get all the chou dofu!");
}
if (GetJournalEntry("quest_sojourner", oPC) >= 41) {
if (sArea == "ocmulgeecaverns") {
AddStruct("Yeah, it's hard work, but at least now I get a bit of respect for it!");
AddStruct("At least it's honest work, ya know what I'm saying?");
AddStruct("It's been a long time comin'...");
}
else {
AddStruct("Shh...don't talk about the Shen Finn here, I'll get in trouble!");
AddStruct("Those Shen Finn slackers should stop playing soldier and get back to work!");
AddStruct("War is for the big folks, we gnomes got more sense than that.");
}
AddStruct("Pao Shifu you jidan!");
}
//PC Squadmember
if (GetLocalObject(OBJECT_SELF, "oSquadLeader") == oPC) {
AddStruct("What now, boss?");
}
//This gives the NPC an oppurtunity to comment on the PC's equipped items
//Equipped Items
if (GetTag(GetItemInSlot(INVENTORY_SLOT_HEAD, oPC)) == "item_procurershat") {
AddStruct("Hey, nice hat!");
}
if (GetTag(GetItemInSlot(INVENTORY_SLOT_CHEST, oPC)) == "marine_officer_uniform") {
AddStruct("Don't you look dashing, Capt. Ogletree!");
AddStruct("I can't believe anyone actually falls for that...");
}
//Now race. You get the idea, any random check you can think of, you can just throw it in.
//Player Race
int iPCRace = GetSubRace(oPC);
if (iPCRace == RACIAL_SUBTYPE_ROCK_GNOME) {
AddStruct("Great...another gnome, just what we need.");
AddStruct("Wei shemne ni xihuan congming ren?");
AddStruct("Didn't we used to date?");
AddStruct("Ni chi doufu ma?");
AddStruct("Really? Who actually plays a gnome?");
}
//This function (see above) does the actual picking. Each item gets an equal weight, just like pulling a raffle //ticket out of a bin. You can alway's just stuff extra copies in there, though, if you want a particular item to //be more probable.
BuildNPCLine();
}
The strength of this approach is that you never have to worry about the math and the probabilities adding up. You just add things as you think about them. The downside, though, is that it's difficult to make sure an item pops up, say 50% of the time. So say you have a town square. You can have a single script that randomly assigns tasks to NPCs in the town square, and everytime you think of a new potential task to add, it's real simple just to throw it in with the others. It's more difficult, though, to say, for example, that 40% of the NPCs will be shopping, 30% selling, and the other 30% doing something else. You could though, have a script that looks for nearby waypoints (like a shop waypoint, or a guardpost waypoint, or a drunken bum waypoint) and adds tasks to the list based on whether or not those waypoints are present.
#65
Posté 31 mars 2012 - 06:28
I thought I had the npcs correctly going to their waypoints and playing their actions 100% correctly. Turned out I didn't. Next step is more error correction code.
#66
Posté 07 avril 2012 - 01:12
Integration of Apep's dynamic commoners ( nwvault.ign.com/View.php Apep granting permission required): this allows commoners to automatically dress, get voicesets, names etc. I wouldn't expect permission problems from Apep as I've worked through some bugs in his system with him. I view this as the "neat"-est thing that can be added.
Duplicate waypoint user detection: [edit: added this 7 April, and it worked on the first try! It also fixed the remaining animation bugs, npcs that elected the same wp would result in one getting bumped, and it would be too far from it's wp, so the animation would not play. Added feature and bugfix all in one!]
ensures an npc doesn't try to occupy the same waypoint that another one already is. Not so important for "cheering crowd", but the sitting and bed activities would benefit. Perhaps the most useful add, even if the benefit isn't highly visible except for specific actions.
Kemo sitting/bed support: for those halfling and dwarf commoners. Benefits the sitting/bed activities. I havnt looked at all at Kemo's system, this may turn out to not be doable. I think it should be doable in theory, maybe not in a 1.0 release.
More detection of "appropriateness": npcs already equip their hands appropriately for activities. They could also dress appropriately, for instance making woodcutters wear leather armor.
Also in "appropriate"-ness: there are animations for female and male dance and seperate activity chances for each, but commoners don't currently only adopt the appropriate one (female npcs can currently choose the male dance animation and vice versa). Would people like commoners forced to adopt the "appropriate" animation for their gender? Would they want males being forced into the male dance animation even if the builder assigned 0% to male dance animation, or would re-selection of activity be preferable (that would mean a 50% chance of female dance
would result in no males and 50% of females dancing) Or just leave it as is with no gender checks (females can play male dance animation and vice versa).
Holiday detection: allow a builder to use an area heartbeat to have a "holiday" setting, giving builders the ability to use a different set of ipoints for holiday action control (maybe the commoners all dance in the town square) This would be mostly on a builder to define when they wanted one, but a local int such as nIsHolidayToday could be set on an area to support that, and an alternate set of "holiday ipoints" could be included, with a small change to default scripting to look at that for that area variable and change the control ipoints appropriately.
Other, better ideas go below, or do you want to see a beta release first to play around with to see what you want?
Modifié par kamal_, 08 avril 2012 - 12:48 .
#67
Posté 07 avril 2012 - 11:42
#68
Posté 07 avril 2012 - 04:54
It can be played around with anytime anyone wants. I back up to dropbox every time I fix or add something.M. Rieder wrote...
I'll be ready to start adding commoners to cities in about 2 months. I'd like to play around with this when the time comes. I'm always looking for a better solution when it comes to ambience - the bane of my modding existence.
Readme edit: clarified (the readme says there is an .erf, there is not one at this time. Use the next link.)
current code/test area, there are extraneous scripts in there for the time stuff, and old backup copies of the needed scripts. In the test area, you can talk with the time lady to advance the time. This link is always the current version until release.
Modifié par kamal_, 08 avril 2012 - 12:13 .
#69
Posté 07 avril 2012 - 08:09
#70
Posté 07 avril 2012 - 08:11
An erf without extraneous scripts will be prepared (like the readme indicates there will be) once it's ready for release. For now, it is what it is.bealzebub wrote...
Is there an .erf version ready for download, without extraneous scripts?
#71
Posté 07 avril 2012 - 10:18
The time randomization code is currently set to 0 randomization, for easier testing.
If someone could go through and test the various activities, letting me know which don't work. I can move on to dealing with duplicate waypoint selection.
edit: I added duplicate waypoint detection, and it worked on the first try! That never happens! :happy:
Modifié par kamal_, 08 avril 2012 - 12:09 .
#72
Posté 10 avril 2012 - 12:29
So I've added a couple related new activities. You can now give a "go home and sleep" activity and commoners will find and move to a random door in the area, play the "use" animation, and go script hidden for 9 hours (8+1 for breakfast). At their wake up time they unhide themselves and pick a new activity based on the time. Go home and sleep until wake time, and go home and sleep until dinner time have also been added. The wake and sleep times are defined in script.
The go home and sleep functions will allow builders to have their streets empty out at night (or day if you want vampire commoners
Modifié par kamal_, 12 avril 2012 - 12:06 .
#73
Posté 13 avril 2012 - 01:32
Next up will be to get the sleep code added to the original sleep functions.
Since no one has chimed in on ideas, I will look at adding Kemo support, and either add that if it seems doable, or clean things up and put out a beta for people to test.





Retour en haut







