public static bool CanHandleChat(NWObject sender) { return(sender.GetLocalBool("MESSAGE_BOARD_LISTENING") == true); }
private static void InitializeAreaSpawns(NWArea area) { var areaSpawn = new AreaSpawn(); // Check for manually placed spawns NWObject obj = GetFirstObjectInArea(area.Object); while (obj.IsValid) { bool isSpawn = obj.ObjectType == ObjectType.Waypoint && obj.GetLocalBool("IS_SPAWN") == true; if (isSpawn) { var spawnType = (ObjectType)obj.GetLocalInt("SPAWN_TYPE"); var objectType = spawnType == 0 || spawnType == ObjectType.Creature ? ObjectType.Creature : spawnType; int spawnTableID = obj.GetLocalInt("SPAWN_TABLE_ID"); int npcGroupID = obj.GetLocalInt("SPAWN_NPC_GROUP_ID"); string behaviourScript = obj.GetLocalString("SPAWN_BEHAVIOUR_SCRIPT"); if (string.IsNullOrWhiteSpace(behaviourScript)) { behaviourScript = obj.GetLocalString("SPAWN_BEHAVIOUR"); } string spawnResref = obj.GetLocalString("SPAWN_RESREF"); float respawnTime = obj.GetLocalFloat("SPAWN_RESPAWN_SECONDS"); string spawnRule = obj.GetLocalString("SPAWN_RULE"); int deathVFXID = obj.GetLocalInt("SPAWN_DEATH_VFX"); AIFlags aiFlags = (AIFlags)obj.GetLocalInt("SPAWN_AI_FLAGS"); bool useResref = true; // No resref specified but a table was, look in the database for a random record. if (string.IsNullOrWhiteSpace(spawnResref) && spawnTableID > 0) { // Pick a random record. var spawnObjects = DataService.SpawnObject.GetAllBySpawnTableID(spawnTableID).ToList(); int count = spawnObjects.Count; int index = count <= 0 ? 0 : RandomService.Random(count); var dbSpawn = spawnObjects[index]; if (dbSpawn != null) { spawnResref = dbSpawn.Resref; useResref = false; if (dbSpawn.NPCGroupID != null && dbSpawn.NPCGroupID > 0) { npcGroupID = Convert.ToInt32(dbSpawn.NPCGroupID); } if (!string.IsNullOrWhiteSpace(dbSpawn.BehaviourScript)) { behaviourScript = dbSpawn.BehaviourScript; } if (!string.IsNullOrWhiteSpace(dbSpawn.SpawnRule)) { spawnRule = dbSpawn.SpawnRule; } if (deathVFXID <= 0) { deathVFXID = dbSpawn.DeathVFXID; } if (aiFlags == AIFlags.None) { aiFlags = dbSpawn.AIFlags; } } } // If we found a resref, spawn the object and add it to the cache. if (!string.IsNullOrWhiteSpace(spawnResref)) { // Delay the creation so that the iteration through the area doesn't get thrown off by new entries. Location location = obj.Location; bool isInstance = area.IsInstance; ObjectSpawn newSpawn; if (useResref) { newSpawn = new ObjectSpawn(location, true, spawnResref, respawnTime); } else { newSpawn = new ObjectSpawn(location, true, spawnTableID, respawnTime); } if (npcGroupID > 0) { newSpawn.NPCGroupID = npcGroupID; } if (deathVFXID > 0) { newSpawn.DeathVFXID = deathVFXID; } if (!string.IsNullOrWhiteSpace(behaviourScript)) { newSpawn.BehaviourScript = behaviourScript; } if (!string.IsNullOrWhiteSpace(spawnRule)) { newSpawn.SpawnRule = spawnRule; } if (aiFlags == AIFlags.None) { newSpawn.AIFlags = aiFlags; } // Instance spawns are one-shot. if (isInstance) { newSpawn.Respawns = false; } if (objectType == ObjectType.Creature) { areaSpawn.Creatures.Add(newSpawn); } else if (objectType == ObjectType.Placeable) { areaSpawn.Placeables.Add(newSpawn); } } } obj = GetNextObjectInArea(area.Object); } AreaSpawns.Add(area, areaSpawn); DelayCommand(1.0f, () => { SpawnResources(area, areaSpawn); }); }
private static void ProcessPerkFeats(NWCreature self) { // Bail early if any of the following is true: // - Creature has a weapon skill queued. // - Creature does not have a PerkFeat cache. // - There are no perk feats in the cache. // - Creature has no target. if (self.GetLocalInt("ACTIVE_WEAPON_SKILL") > 0) { return; } if (!self.Data.ContainsKey("PERK_FEATS")) { return; } Dictionary <int, AIPerkDetails> cache = self.Data["PERK_FEATS"]; if (cache.Count <= 0) { return; } NWObject target = _.GetAttackTarget(self); if (!target.IsValid) { return; } // todo: GetEffectType() returns EFFECT_TYPE_INVALIDEFFECT for knockdown effects. // todo: The following code is causing a segfault crash... look into other solutions or figure out what's causing that. // target.Effects.Any(x => NWNXEffect.UnpackEffect(x).Type == (int)EffectTypeEngine.Knockdown) || // Potential workaround: if (target.GetLocalBool("KNOCKDOWN")) return; if (target.GetLocalBool("KNOCKDOWN")) { return; } if (target.Effects.Any(x => _.GetEffectTag(x) == "TRANQUILIZER_EFFECT")) { return; } // Pull back whatever concentration effect is currently active, if any. var concentration = AbilityService.GetActiveConcentrationEffect(self); // Exclude any concentration effects, if necessary, then randomize potential feats to use. var randomizedFeatIDs = concentration.Type == PerkType.Unknown ? cache.Values // No concentration exclusions : cache.Values.Where(x => x.ExecutionType != PerkExecutionType.ConcentrationAbility); // Exclude concentration abilities randomizedFeatIDs = randomizedFeatIDs.OrderBy(o => RandomService.Random()); foreach (var perkDetails in randomizedFeatIDs) { // Move to next feat if this creature cannot use this one. if (!AbilityService.CanUsePerkFeat(self, target, (Feat)perkDetails.FeatID)) { continue; } self.AssignCommand(() => { _.ActionUseFeat((Feat)perkDetails.FeatID, target); }); break; } }