示例#1
0
        private void HandleAddItemToItemCollector(NWPlayer oPC, NWPlaceable container, NWItem oItem)
        {
            string resref = oItem.Resref;

            if (resref == SubmitQuestItemResref)
            {
                return;
            }

            int        questID = container.GetLocalInt("QUEST_ID");
            QuestState state   = _db.PCQuestStatus.Single(x => x.PlayerID == oPC.GlobalID && x.QuestID == questID).CurrentQuestState;

            foreach (QuestRequiredItemList reqItem in state.QuestRequiredItemLists)
            {
                if (reqItem.Resref == resref)
                {
                    return;
                }
            }

            _.CopyItem(oItem.Object, oPC.Object, TRUE);
            oItem.Destroy();
            oPC.SendMessage(_color.Red("That item is not required for this quest."));
        }
示例#2
0
        public void OnHitCastSpell(NWPlayer oPC)
        {
            NWObject oTarget = _.GetSpellTargetObject();

            HandleGrenadeProficiency(oPC, oTarget);
            HandlePlasmaCellPerk(oPC, oTarget);
            int activeWeaponSkillID = oPC.GetLocalInt("ACTIVE_WEAPON_SKILL");

            if (activeWeaponSkillID <= 0)
            {
                return;
            }

            PCPerk entity = _data.GetAll <PCPerk>().Single(x => x.PlayerID == oPC.GlobalID && x.PerkID == activeWeaponSkillID);
            var    perk   = _data.Get <Data.Entity.Perk>(entity.PerkID);

            App.ResolveByInterface <IPerk>("Perk." + perk.ScriptName, (script) =>
            {
                if (script.CanCastSpell(oPC, oTarget))
                {
                    script.OnImpact(oPC, oTarget, entity.PerkLevel);

                    if (oTarget.IsNPC)
                    {
                        ApplyEnmity(oPC, oTarget.Object, perk);
                    }
                }
                else
                {
                    oPC.SendMessage(script.CannotCastSpellMessage(oPC, oTarget) ?? "That ability cannot be used at this time.");
                }

                oPC.DeleteLocalString("ACTIVE_WEAPON_SKILL_UUID");
                oPC.DeleteLocalInt("ACTIVE_WEAPON_SKILL");
            });
        }
示例#3
0
        public bool Run(params object[] args)
        {
            NWPlayer    player = (_.GetLastUsedBy());
            NWPlaceable device = (Object.OBJECT_SELF);

            // If a structure ID is defined, we need to make sure the building is set to Workshop mode.
            string structureID = device.GetLocalString("PC_BASE_STRUCTURE_ID");

            if (!string.IsNullOrWhiteSpace(structureID))
            {
                Guid structureGuid = new Guid(structureID);
                var  structure     = DataService.Get <PCBaseStructure>(structureGuid);

                // Workbenches and crafting devices can only be used inside
                // buildings set to "Workshop" mode.
                if (structure.ParentPCBaseStructureID != null)
                {
                    var buildingStructure = DataService.Get <PCBaseStructure>(structure.ParentPCBaseStructureID);
                    var modeType          = (StructureModeType)buildingStructure.StructureModeID;

                    if (modeType != StructureModeType.Workshop)
                    {
                        player.FloatingText("Workbenches and crafting devices may only be used when the building is set to 'Workshop' mode.");
                        return(false);
                    }
                }
            }

            if (player.IsBusy)
            {
                player.SendMessage("You are too busy to do that right now.");
                return(false);
            }
            DialogService.StartConversation(player, device, "CraftingDevice");
            return(true);
        }
示例#4
0
        public void ApplyEffects(NWCreature user, NWItem item, NWObject target, Location targetLocation, CustomData customData)
        {
            NWArea   area          = user.Area;
            NWPlayer player        = new NWPlayer(user);
            string   structureID   = area.GetLocalString("PC_BASE_STRUCTURE_ID");
            Guid     structureGuid = new Guid(structureID);

            PCBaseStructure pcbs      = DataService.PCBaseStructure.GetByID(structureGuid);
            BaseStructure   structure = DataService.BaseStructure.GetByID(pcbs.BaseStructureID);

            var dbItem = new PCBaseStructureItem
            {
                PCBaseStructureID = pcbs.ID,
                ItemGlobalID      = item.GlobalID.ToString(),
                ItemName          = item.Name,
                ItemResref        = item.Resref,
                ItemTag           = item.Tag,
                ItemObject        = SerializationService.Serialize(item)
            };

            DataService.SubmitDataChange(dbItem, DatabaseActionType.Insert);
            player.SendMessage(item.Name + " was successfully added to your ship.  Access the cargo bay via the ship's computer to remove it.");
            item.Destroy();
        }
示例#5
0
        private int ProcessProperty(int amount, int maxBonuses, ComponentBonusType bonus, float levelsPerBonus = 1.0f)
        {
            string resref  = _componentType.ReassembledResref;
            int    penalty = 0;
            int    luck    = PerkService.GetPCPerkLevel(_player, PerkType.Lucky) + (_playerItemStats.Luck / 3);
            int    xp      = 0;

            ItemPropertyUnpacked bonusIP = new ItemPropertyUnpacked
            {
                Property       = (int)CustomItemPropertyType.ComponentBonus,
                SubType        = (int)bonus,
                CostTable      = 62,
                CostTableValue = 0,
                Param1         = 255,
                Param1Value    = 0,
                UsesPerDay     = 255,
                ChanceToAppear = 100,
                IsUseable      = true,
                SpellID        = -1
            };

            while (amount > 0)
            {
                int chanceToTransfer = CraftService.CalculateReassemblyChance(_player, penalty);
                // Roll to see if the item can be created.
                bool success = RandomService.Random(0, 100) <= chanceToTransfer;

                // Do a lucky roll if we failed the first time.
                if (!success && luck > 0 && RandomService.Random(0, 100) <= luck)
                {
                    _player.SendMessage("Lucky reassemble!");
                    success = true;
                }

                if (amount >= maxBonuses)
                {
                    if (success)
                    {
                        int levelIncrease = (int)(maxBonuses * levelsPerBonus);
                        // Roll succeeded. Create item.
                        bonusIP.CostTableValue = maxBonuses;
                        ItemProperty bonusIPPacked = NWNXItemProperty.PackIP(bonusIP);
                        NWItem       item          = _.CreateItemOnObject(resref, _player);
                        item.RecommendedLevel = levelIncrease;
                        BiowareXP2.IPSafeAddItemProperty(item, bonusIPPacked, 0.0f, AddItemPropertyPolicy.ReplaceExisting, true, false);

                        xp += (150 * maxBonuses + RandomService.Random(0, 5));
                    }
                    else
                    {
                        _player.SendMessage(ColorTokenService.Red("You failed to create a component. (+" + maxBonuses + ")"));
                        xp += (50 + RandomService.Random(0, 5));
                    }
                    // Penalty to chance increases regardless if item was created or not.
                    penalty += (maxBonuses * 5);
                    amount  -= maxBonuses;
                }
                else
                {
                    if (success)
                    {
                        int levelIncrease = (int)(amount * levelsPerBonus);
                        bonusIP.CostTableValue = amount;
                        ItemProperty bonusIPPacked = NWNXItemProperty.PackIP(bonusIP);
                        NWItem       item          = _.CreateItemOnObject(resref, _player);
                        item.RecommendedLevel = levelIncrease;
                        BiowareXP2.IPSafeAddItemProperty(item, bonusIPPacked, 0.0f, AddItemPropertyPolicy.ReplaceExisting, true, false);

                        xp += (150 * amount + RandomService.Random(0, 5));
                    }
                    else
                    {
                        _player.SendMessage(ColorTokenService.Red("You failed to create a component. (+" + amount + ")"));
                        xp += (50 + RandomService.Random(0, 5));
                    }
                    break;
                }
            }

            return(xp);
        }
示例#6
0
        public void OnModuleActivatedItem()
        {
            NWPlayer user           = (_.GetItemActivator());
            NWItem   oItem          = (_.GetItemActivated());
            NWObject target         = (_.GetItemActivatedTarget());
            Location targetLocation = _.GetItemActivatedTargetLocation();

            string className = oItem.GetLocalString("JAVA_SCRIPT");

            if (string.IsNullOrWhiteSpace(className))
            {
                className = oItem.GetLocalString("ACTIVATE_JAVA_SCRIPT");
            }
            if (string.IsNullOrWhiteSpace(className))
            {
                className = oItem.GetLocalString("JAVA_ACTION_SCRIPT");
            }
            if (string.IsNullOrWhiteSpace(className))
            {
                className = oItem.GetLocalString("SCRIPT");
            }
            if (string.IsNullOrWhiteSpace(className))
            {
                return;
            }

            user.ClearAllActions();

            if (user.IsBusy)
            {
                user.SendMessage("You are busy.");
                return;
            }

            // Remove "Item." prefix if it exists.
            if (className.StartsWith("Item."))
            {
                className = className.Substring(5);
            }

            App.ResolveByInterface <IActionItem>("Item." + className, (item) =>
            {
                string invalidTargetMessage = item.IsValidTarget(user, oItem, target, targetLocation);
                if (!string.IsNullOrWhiteSpace(invalidTargetMessage))
                {
                    user.SendMessage(invalidTargetMessage);
                    return;
                }

                float maxDistance = item.MaxDistance(user, oItem, target, targetLocation);
                if (maxDistance > 0.0f)
                {
                    if (target.IsValid &&
                        (_.GetDistanceBetween(user.Object, target.Object) > maxDistance ||
                         user.Area.Resref != target.Area.Resref))
                    {
                        user.SendMessage("Your target is too far away.");
                        return;
                    }
                    else if (!target.IsValid &&
                             (_.GetDistanceBetweenLocations(user.Location, targetLocation) > maxDistance ||
                              user.Area.Resref != ((NWArea)_.GetAreaFromLocation(targetLocation)).Resref))
                    {
                        user.SendMessage("That location is too far away.");
                        return;
                    }
                }

                CustomData customData = item.StartUseItem(user, oItem, target, targetLocation);
                float delay           = item.Seconds(user, oItem, target, targetLocation, customData);
                int animationID       = item.AnimationID();
                bool faceTarget       = item.FaceTarget();
                Vector userPosition   = user.Position;

                user.AssignCommand(() =>
                {
                    user.IsBusy = true;
                    if (faceTarget)
                    {
                        _.SetFacingPoint(!target.IsValid ? _.GetPositionFromLocation(targetLocation) : target.Position);
                    }
                    if (animationID > 0)
                    {
                        _.ActionPlayAnimation(animationID, 1.0f, delay);
                    }
                });

                _nwnxPlayer.StartGuiTimingBar(user, delay, string.Empty);
                user.DelayEvent <FinishActionItem>(
                    delay,
                    className,
                    user,
                    oItem,
                    target,
                    targetLocation,
                    userPosition,
                    customData);
            });
        }
示例#7
0
        public bool Run(params object[] args)
        {
            NWPlaceable oSite = NWPlaceable.Wrap(Object.OBJECT_SELF);
            NWPlayer    oPC   = NWPlayer.Wrap(_.GetLastAttacker(oSite.Object));
            int         constructionSiteID = _structure.GetConstructionSiteID(oSite);

            if (constructionSiteID <= 0)
            {
                oPC.FloatingText("You must select a blueprint before you can build.");
                oPC.ClearAllActions();
                return(true);
            }

            NWItem weapon     = NWItem.Wrap(_.GetLastWeaponUsed(oPC.Object));
            int    weaponType = weapon.BaseItemType;

            if (weaponType != BASE_ITEM_LIGHTHAMMER)
            {
                oPC.FloatingText("A hammer must be equipped to build this structure.");
                oPC.ClearAllActions();
                return(true);
            }

            // Offhand weapons don't contribute to building.
            if (weapon.Equals(oPC.LeftHand))
            {
                return(true);
            }

            if (!_structure.IsConstructionSiteValid(oSite))
            {
                oPC.FloatingText("Construction site is invalid. Please click the construction site to find out more.");
                oPC.ClearAllActions();
                return(true);
            }


            Data.Entities.ConstructionSite entity = _structure.GetConstructionSiteByID(constructionSiteID);


            if (weapon.CraftTierLevel < entity.StructureBlueprint.CraftTierLevel)
            {
                oPC.FloatingText("Your hammer cannot be used with this blueprint. (Required Tool Level: " + entity.StructureBlueprint.CraftTierLevel + ")");
                oPC.ClearAllActions();
                return(true);
            }

            int    rank          = _skill.GetPCSkill(oPC, SkillType.Construction).Rank;
            int    mangleChance  = CalculateMangleChance(oPC, entity.StructureBlueprint.Level, rank);
            bool   isMangle      = _random.Random(100) + 1 <= mangleChance;
            bool   foundResource = false;
            string updateMessage = "You lack the necessary resources...";

            int totalAmount = 0;

            foreach (ConstructionSiteComponent comp in entity.ConstructionSiteComponents)
            {
                if (comp.Quantity > 0 && !foundResource)
                {
                    NWItem item = NWItem.Wrap(_.GetItemPossessedBy(oPC.Object, comp.StructureComponent.Resref));
                    if (item.IsValid)
                    {
                        int reuseChance = isMangle ? 0 : _perk.GetPCPerkLevel(oPC, PerkType.ConservativeConstruction) * 2 + _perk.GetPCPerkLevel(oPC, PerkType.Lucky);
                        if (_random.Random(100) + 1 <= reuseChance)
                        {
                            oPC.SendMessage("You conserve a resource...");
                        }
                        else
                        {
                            item.ReduceItemStack();
                        }

                        if (isMangle)
                        {
                            oPC.SendMessage(_color.Red("You mangle a resource due to your lack of skill..."));
                            return(true);
                        }

                        string name = _item.GetNameByResref(comp.StructureComponent.Resref);
                        comp.Quantity--;
                        updateMessage = "You need " + comp.Quantity + " " + name + " to complete this project.";
                        foundResource = true;
                    }
                }
                totalAmount += comp.Quantity;
            }

            oPC.DelayCommand(() => oPC.SendMessage(updateMessage), 0.75f);

            if (totalAmount <= 0)
            {
                _structure.CompleteStructure(oSite);
            }
            else if (foundResource)
            {
                _structure.SaveChanges();
                _durability.RunItemDecay(oPC, weapon);

                if (entity.StructureBlueprint.GivesSkillXP)
                {
                    int xp = (int)_skill.CalculateSkillAdjustedXP(100, 0, rank);
                    _skill.GiveSkillXP(oPC, SkillType.Construction, xp);
                }

                // Speedy Builder - Grants haste for 8 seconds
                int hasteChance = _perk.GetPCPerkLevel(oPC, PerkType.SpeedyBuilder) * 10;

                if (hasteChance > 0)
                {
                    hasteChance += _perk.GetPCPerkLevel(oPC, PerkType.Lucky) * 2;
                }

                PlayerCharacter pcEntity = _player.GetPlayerEntity(oPC);
                if (pcEntity.BackgroundID == (int)BackgroundType.ConstructionBuilder)
                {
                    hasteChance += 10;
                }

                if (_random.Random(100) + 1 <= hasteChance)
                {
                    _.ApplyEffectToObject(DURATION_TYPE_TEMPORARY, _.EffectHaste(), oPC.Object, 8.0f);
                }
            }
            else
            {
                oPC.ClearAllActions();
            }
            return(true);
        }
示例#8
0
        private void DeathFunction(NWPlayer oPC, int nDC)
        {
            if (!oPC.IsValid)
            {
                return;
            }
            int iHP = oPC.CurrentHP;

            //Player Rolls a random number between 1 and 20+ConMod
            int iRoll = 20 + oPC.ConstitutionModifier;

            iRoll = _random.Random(iRoll) + 1;

            //Sanity Check
            if (nDC > 30)
            {
                nDC = 30;
            }
            else if (nDC < 4)
            {
                nDC = 4;
            }

            if (iHP <= 0)
            {
                if (iRoll >= nDC) //Stabilize
                {
                    nDC -= 2;
                    _.ApplyEffectToObject(DURATION_TYPE_INSTANT, _.EffectHeal(1), oPC.Object);
                    oPC.DelayCommand(() =>
                    {
                        DeathFunction(oPC, nDC);
                    }, 3.0f);
                }
                else  //Failed!
                {
                    if (_random.Random(2) + 1 == 1)
                    {
                        nDC++;
                    }
                    Effect eResult = _.EffectDamage(1);

                    //Death!
                    if (iHP <= -9)
                    {
                        _.ApplyEffectToObject(DURATION_TYPE_INSTANT, _.EffectVisualEffect(VFX_IMP_DEATH), oPC.Object);
                        _.ApplyEffectToObject(DURATION_TYPE_INSTANT, _.EffectDeath(), oPC.Object);
                        return;
                    }
                    else
                    {
                        oPC.SendMessage(_color.Orange("You failed to stabilize this round."));
                    }
                    _.ApplyEffectToObject(DURATION_TYPE_INSTANT, eResult, oPC.Object);

                    oPC.DelayCommand(() =>
                    {
                        DeathFunction(oPC, nDC);
                    }, 3.0f);
                }
            }
        }
示例#9
0
        public bool Run(params object[] args)
        {
            NWPlaceable point = NWPlaceable.Wrap(Object.OBJECT_SELF);
            const int   baseChanceToFullyHarvest = 50;
            bool        alwaysDestroys           = point.GetLocalInt("FORAGE_POINT_ALWAYS_DESTROYS") == 1;

            NWPlayer oPC             = NWPlayer.Wrap(_.GetLastOpenedBy());
            bool     hasBeenSearched = point.GetLocalInt("FORAGE_POINT_FULLY_HARVESTED") == 1;

            if (hasBeenSearched)
            {
                oPC.SendMessage("There's nothing left to harvest here...");
                return(true);
            }

            // Not fully harvested but the timer hasn't counted down yet.
            int refillTick = point.GetLocalInt("FORAGE_POINT_REFILL_TICKS");

            if (refillTick > 0)
            {
                oPC.SendMessage("You couldn't find anything new here. Check back later...");
                return(true);
            }

            if (!oPC.IsPlayer && !oPC.IsDM)
            {
                return(false);
            }
            PCSkill pcSkill = _skill.GetPCSkill(oPC, SkillType.Forage);

            if (pcSkill == null)
            {
                return(false);
            }

            int lootTableID = point.GetLocalInt("FORAGE_POINT_LOOT_TABLE_ID");
            int level       = point.GetLocalInt("FORAGE_POINT_LEVEL");
            int rank        = pcSkill.Rank;
            int delta       = level - rank;

            if (delta > 8)
            {
                oPC.SendMessage("You aren't skilled enough to forage through this. (Required Level: " + (level - 8) + ")");
                oPC.AssignCommand(() => _.ActionInteractObject(point.Object));
                return(true);
            }

            int dc = 6 + delta;

            if (dc <= 4)
            {
                dc = 4;
            }
            int searchAttempts = 1 + CalculateSearchAttempts(oPC);

            int luck = _perk.GetPCPerkLevel(oPC, PerkType.Lucky) + oPC.EffectiveLuckBonus;

            if (_random.Random(100) + 1 <= luck / 2)
            {
                dc--;
            }

            oPC.AssignCommand(() => _.ActionPlayAnimation(ANIMATION_LOOPING_GET_LOW, 1.0f, 2.0f));

            for (int attempt = 1; attempt <= searchAttempts; attempt++)
            {
                int roll = _random.Random(20) + 1;
                if (roll >= dc)
                {
                    oPC.FloatingText(_color.SkillCheck("Search: *success*: (" + roll + " vs. DC: " + dc + ")"));
                    ItemVO spawnItem = _loot.PickRandomItemFromLootTable(lootTableID);

                    if (spawnItem == null)
                    {
                        return(false);
                    }

                    if (!string.IsNullOrWhiteSpace(spawnItem.Resref) && spawnItem.Quantity > 0)
                    {
                        _.CreateItemOnObject(spawnItem.Resref, point.Object, spawnItem.Quantity);
                    }

                    float xp = _skill.CalculateRegisteredSkillLevelAdjustedXP(50, level, rank);
                    _skill.GiveSkillXP(oPC, SkillType.Forage, (int)xp);
                }
                else
                {
                    oPC.FloatingText(_color.SkillCheck("Search: *failure*: (" + roll + " vs. DC: " + dc + ")"));

                    float xp = _skill.CalculateRegisteredSkillLevelAdjustedXP(10, level, rank);
                    _skill.GiveSkillXP(oPC, SkillType.Forage, (int)xp);
                }
                dc += _random.Random(3) + 1;
            }

            if (_random.Random(100) + 1 <= 3)
            {
                _food.DecreaseHungerLevel(oPC, 1);
            }


            // Chance to destroy the forage point.
            int chanceToFullyHarvest = baseChanceToFullyHarvest - (_perk.GetPCPerkLevel(oPC, PerkType.CarefulForager) * 5);
            int growingPlantID       = point.GetLocalInt("GROWING_PLANT_ID");

            if (growingPlantID > 0)
            {
                Data.Entities.GrowingPlant growingPlant = _farming.GetGrowingPlantByID(growingPlantID);
                chanceToFullyHarvest = chanceToFullyHarvest - (growingPlant.LongevityBonus);
            }

            if (chanceToFullyHarvest <= 5)
            {
                chanceToFullyHarvest = 5;
            }

            if (alwaysDestroys || _random.Random(100) + 1 <= chanceToFullyHarvest)
            {
                point.SetLocalInt("FORAGE_POINT_FULLY_HARVESTED", 1);
                oPC.SendMessage("This resource has been fully harvested...");
            }
            // Otherwise the forage point will be refilled in 10-20 minutes.
            else
            {
                point.SetLocalInt("FORAGE_POINT_REFILL_TICKS", 100 + _random.Random(100));
            }

            point.SetLocalInt("FORAGE_POINT_DESPAWN_TICKS", 30);

            return(true);
        }
示例#10
0
        public void ApplyEffects(NWCreature user, NWItem item, NWObject target, Location targetLocation, CustomData customData)
        {
            NWPlayer player         = user.Object;
            var      effectiveStats = PlayerStatService.GetPlayerItemEffectiveStats(player);
            int      skillRank      = SkillService.GetPCSkillRank(player, SkillType.Medicine);
            int      perkLevel      = PerkService.GetCreaturePerkLevel(player, PerkType.ResuscitationDevices);
            int      rank           = item.GetLocalInt("RANK");
            int      baseHeal;

            switch (rank)
            {
            case 1:
                baseHeal = 1;
                break;

            case 2:
                baseHeal = 11;
                break;

            case 3:
                baseHeal = 31;
                break;

            case 4:
                baseHeal = 51;
                break;

            default: return;
            }

            baseHeal += perkLevel * 2;
            baseHeal += effectiveStats.Medicine / 2;
            baseHeal += item.MedicineBonus / 2;

            int   delta = item.RecommendedLevel - skillRank;
            float effectivenessPercent = 1.0f;

            if (delta > 0)
            {
                effectivenessPercent = effectivenessPercent - (delta * 0.1f);
            }
            if (target.IsPlayer)
            {
                baseHeal = (int)(baseHeal * effectivenessPercent);
                Player dbPlayer  = DataService.Player.GetByID(target.GlobalID);
                int    fpRecover = (int)(dbPlayer.MaxFP * (0.01f * baseHeal));
                int    hpRecover = (int)(target.MaxHP * (0.01f * baseHeal));

                _.PlaySound("use_bacta");
                _.ApplyEffectToObject(DURATION_TYPE_INSTANT, _.EffectResurrection(), target);
                _.ApplyEffectToObject(DURATION_TYPE_INSTANT, _.EffectHeal(hpRecover), target);
                dbPlayer.CurrentFP = fpRecover;
                DataService.SubmitDataChange(dbPlayer, DatabaseActionType.Update);
                player.SendMessage("You successfully resuscitate " + target.Name + "!");

                int xp = (int)SkillService.CalculateRegisteredSkillLevelAdjustedXP(600, item.RecommendedLevel, skillRank);
                SkillService.GiveSkillXP(player, SkillType.Medicine, xp);
            }
            else
            {
                baseHeal = (int)(baseHeal * effectivenessPercent);
                int hpRecover = (int)(target.MaxHP * (0.01f * baseHeal));
                _.ApplyEffectToObject(DURATION_TYPE_INSTANT, _.EffectResurrection(), target);
                _.ApplyEffectToObject(DURATION_TYPE_INSTANT, _.EffectHeal(hpRecover), target);
                player.SendMessage("You successfully resuscitate " + target.Name + "!");
            }
        }
示例#11
0
        public bool Run(params object[] args)
        {
            NWPlaceable terminal = Object.OBJECT_SELF;
            int         bankID   = terminal.GetLocalInt("BANK_ID");

            if (bankID <= 0)
            {
                return(false);
            }

            NWPlayer player      = _.GetLastDisturbed();
            NWItem   item        = _.GetInventoryDisturbItem();
            int      disturbType = _.GetInventoryDisturbType();
            int      itemCount   = terminal.InventoryItems.Count();
            int      itemLimit   = terminal.GetLocalInt("BANK_LIMIT");

            if (itemLimit <= 0)
            {
                itemLimit = 20;
            }

            if (disturbType == INVENTORY_DISTURB_TYPE_ADDED)
            {
                if (_.GetHasInventory(item) == TRUE)
                {
                    item.SetLocalInt("RETURNING_ITEM", TRUE);
                    _item.ReturnItem(player, item);
                    player.SendMessage(_color.Red("Containers cannot currently be stored inside banks."));
                    return(false);
                }

                if (itemCount > itemLimit)
                {
                    _item.ReturnItem(player, item);
                    player.SendMessage(_color.Red("No more items can be placed inside."));
                }
                else
                {
                    BankItem itemEntity = new BankItem
                    {
                        ItemName   = item.Name,
                        ItemTag    = item.Tag,
                        ItemResref = item.Resref,
                        ItemID     = item.GlobalID.ToString(),
                        ItemObject = _serialization.Serialize(item),
                        BankID     = bankID,
                        PlayerID   = player.GlobalID,
                        DateStored = DateTime.UtcNow
                    };

                    _data.SubmitDataChange(itemEntity, DatabaseActionType.Insert);
                }
            }
            else if (disturbType == INVENTORY_DISTURB_TYPE_REMOVED)
            {
                if (item.GetLocalInt("RETURNING_ITEM") == TRUE)
                {
                    item.DeleteLocalInt("RETURNING_ITEM");
                }
                else
                {
                    var record = _data.Single <BankItem>(x => x.ItemID == item.GlobalID.ToString());
                    _data.SubmitDataChange(record, DatabaseActionType.Delete);
                }
            }

            player.SendMessage(_color.White("Item Limit: " + (itemCount > itemLimit ? itemLimit : itemCount) + " / ") + _color.Red("" + itemLimit));
            return(true);
        }
示例#12
0
        public void ApplyEffects(NWCreature user, NWItem runeItem, NWObject target, Location targetLocation, CustomData customData)
        {
            NWPlayer  player                = NWPlayer.Wrap(user.Object);
            NWItem    targetItem            = NWItem.Wrap(target.Object);
            RuneSlots slots                 = _rune.GetRuneSlots(targetItem);
            CustomItemPropertyType runeType = _rune.GetRuneType(runeItem);
            int runeID = runeItem.GetLocalInt("RUNE_ID");

            string[] runeArgs      = runeItem.GetLocalString("RUNE_VALUE").Split(',');
            int      runeLevel     = runeItem.RecommendedLevel;
            int      levelIncrease = runeItem.LevelIncrease;

            var   dbRune = _db.Runes.Single(x => x.RuneID == runeID && x.IsActive);
            IRune rune   = App.ResolveByInterface <IRune>("Rune." + dbRune.Script);

            rune.Apply(player, targetItem, runeArgs);

            string description  = rune.Description(player, targetItem, runeArgs);
            bool   usePrismatic = false;

            switch (runeType)
            {
            case CustomItemPropertyType.RedRune:
                if (slots.FilledRedSlots < slots.RedSlots)
                {
                    targetItem.SetLocalInt("RUNIC_SLOT_RED_" + (slots.FilledRedSlots + 1), runeID);
                    targetItem.SetLocalString("RUNIC_SLOT_RED_DESC_" + (slots.FilledRedSlots + 1), description);
                    player.SendMessage("Rune installed into " + _color.Red("red") + " slot #" + (slots.FilledRedSlots + 1));
                }
                else
                {
                    usePrismatic = true;
                }
                break;

            case CustomItemPropertyType.BlueRune:
                if (slots.FilledBlueSlots < slots.BlueSlots)
                {
                    targetItem.SetLocalInt("RUNIC_SLOT_BLUE_" + (slots.FilledBlueSlots + 1), runeID);
                    targetItem.SetLocalString("RUNIC_SLOT_BLUE_DESC_" + (slots.FilledBlueSlots + 1), description);
                    player.SendMessage("Rune installed into " + _color.Blue("blue") + " slot #" + (slots.FilledBlueSlots + 1));
                }
                else
                {
                    usePrismatic = true;
                }
                break;

            case CustomItemPropertyType.GreenRune:
                if (slots.FilledBlueSlots < slots.GreenSlots)
                {
                    targetItem.SetLocalInt("RUNIC_SLOT_GREEN_" + (slots.FilledGreenSlots + 1), runeID);
                    targetItem.SetLocalString("RUNIC_SLOT_GREEN_DESC_" + (slots.FilledGreenSlots + 1), description);
                    player.SendMessage("Rune installed into " + _color.Green("green") + " slot #" + (slots.FilledGreenSlots + 1));
                }
                else
                {
                    usePrismatic = true;
                }
                break;

            case CustomItemPropertyType.YellowRune:
                if (slots.FilledBlueSlots < slots.YellowSlots)
                {
                    targetItem.SetLocalInt("RUNIC_SLOT_YELLOW_" + (slots.FilledYellowSlots + 1), runeID);
                    targetItem.SetLocalString("RUNIC_SLOT_YELLOW_DESC_" + (slots.FilledYellowSlots + 1), description);
                    player.SendMessage("Rune installed into " + _color.Yellow("yellow") + " slot #" + (slots.FilledYellowSlots + 1));
                }
                else
                {
                    usePrismatic = true;
                }
                break;
            }

            if (usePrismatic)
            {
                string prismaticText = _rune.PrismaticString();
                targetItem.SetLocalInt("RUNIC_SLOT_PRISMATIC_" + (slots.FilledPrismaticSlots + 1), runeID);
                targetItem.SetLocalString("RUNIC_SLOT_PRISMATIC_DESC_" + (slots.FilledPrismaticSlots + 1), description);
                player.SendMessage("Rune installed into " + prismaticText + " slot #" + (slots.FilledPrismaticSlots + 1));
            }

            targetItem.RecommendedLevel += levelIncrease;
            runeItem.Destroy();

            SkillType skillType;

            if (_item.ArmorBaseItemTypes.Contains(targetItem.BaseItemType))
            {
                skillType = SkillType.Armorsmith;
            }
            else if (_item.WeaponBaseItemTypes.Contains(targetItem.BaseItemType))
            {
                skillType = SkillType.Weaponsmith;
            }
            else
            {
                return;
            }

            PCSkill pcSkill = _skill.GetPCSkill(player, skillType);
            int     xp      = (int)_skill.CalculateRegisteredSkillLevelAdjustedXP(400, runeLevel, pcSkill.Rank);

            _skill.GiveSkillXP(player, skillType, xp);
        }
示例#13
0
        public bool Run(params object[] args)
        {
            NWPlaceable container = NWPlaceable.Wrap(Object.OBJECT_SELF);
            NWPlayer    oPC       = NWPlayer.Wrap(_.GetLastDisturbed());
            int         type      = _.GetInventoryDisturbType();
            NWItem      item      = NWItem.Wrap(_.GetInventoryDisturbItem());

            if (type != INVENTORY_DISTURB_TYPE_ADDED)
            {
                return(false);
            }

            int plantID = item.GetLocalInt("PLANT_ID");

            if (plantID <= 0)
            {
                _item.ReturnItem(oPC, item);
                oPC.SendMessage("You cannot plant that item.");
                return(true);
            }

            Plant plant = _farming.GetPlantByID(plantID);

            if (plant == null)
            {
                _item.ReturnItem(oPC, item);
                oPC.SendMessage("You cannot plant that item.");
                return(true);
            }

            PCSkill pcSkill = _skill.GetPCSkill(oPC, SkillType.Farming);
            int     rank    = 0;

            if (pcSkill != null)
            {
                rank = pcSkill.Rank;
            }

            if (rank + 2 < plant.Level)
            {
                _item.ReturnItem(oPC, item);
                oPC.SendMessage("You do not have enough Farming skill to plant that seed. (Required: " + (plant.Level - 2) + ")");
                return(true);
            }

            item.Destroy();

            string   areaTag       = container.Area.Tag;
            Location plantLocation = container.Location;
            int      perkBonus     = _perk.GetPCPerkLevel(oPC, PerkType.FarmingEfficiency) * 2;
            int      ticks         = (int)(plant.BaseTicks - ((_perk.GetPCPerkLevel(oPC, PerkType.ExpertFarmer) * 0.05f)) * plant.BaseTicks);

            Data.Entities.GrowingPlant growingPlant = new Data.Entities.GrowingPlant();
            growingPlant.PlantID             = plant.PlantID;
            growingPlant.RemainingTicks      = ticks;
            growingPlant.LocationAreaTag     = areaTag;
            growingPlant.LocationOrientation = _.GetFacingFromLocation(plantLocation);
            growingPlant.LocationX           = _.GetPositionFromLocation(plantLocation).m_X;
            growingPlant.LocationY           = _.GetPositionFromLocation(plantLocation).m_Y;
            growingPlant.LocationZ           = _.GetPositionFromLocation(plantLocation).m_Z;
            growingPlant.IsActive            = true;
            growingPlant.DateCreated         = DateTime.UtcNow;
            growingPlant.LongevityBonus      = perkBonus;

            _db.GrowingPlants.Add(growingPlant);
            _db.SaveChanges();

            NWPlaceable hole     = NWPlaceable.Wrap(container.GetLocalObject("FARM_SMALL_HOLE"));
            NWPlaceable plantPlc = NWPlaceable.Wrap(_.CreateObject(OBJECT_TYPE_PLACEABLE, "growing_plant", hole.Location));

            plantPlc.SetLocalInt("GROWING_PLANT_ID", growingPlant.GrowingPlantID);
            plantPlc.Name = "Growing Plant (" + plant.Name + ")";

            container.Destroy();
            hole.Destroy();

            int xp = (int)_skill.CalculateRegisteredSkillLevelAdjustedXP(200, plant.Level, rank);

            if (_random.Random(100) + 1 <= _perk.GetPCPerkLevel(oPC, PerkType.Lucky) + oPC.EffectiveLuckBonus)
            {
                xp *= 2;
            }

            _skill.GiveSkillXP(oPC, SkillType.Farming, xp);
            return(true);
        }
示例#14
0
        public void OnImpact(NWPlayer player, NWObject target, int level, int spellFeatID)
        {
            float length;
            int   damage;

            switch (level)
            {
            case 1:
                damage = RandomService.D4(1);
                length = 3;
                break;

            case 2:
                damage = RandomService.D4(1);
                length = 6;
                break;

            case 3:
                damage = RandomService.D6(1);
                length = 6;
                break;

            case 4:
                damage = RandomService.D8(1);
                length = 6;
                break;

            case 5:
                damage = RandomService.D8(1);
                length = 9;
                break;

            default: return;
            }
            SkillService.RegisterPCToNPCForSkill(player, target, SkillType.ForceCombat);

            // Resistance affects length for this perk.
            ForceResistanceResult resistance = CombatService.CalculateResistanceRating(player, target.Object, ForceAbilityType.Mind);

            length = length * resistance.Amount;

            if (length <= 0.0f || resistance.Type != ResistanceType.Zero)
            {
                player.SendMessage("Your Force Push effect was resisted.");
                return;
            }

            var effectiveStats = PlayerStatService.GetPlayerItemEffectiveStats(player);
            int luck           = PerkService.GetPCPerkLevel(player, PerkType.Lucky) + effectiveStats.Luck;

            if (RandomService.Random(100) + 1 <= luck)
            {
                length = length * 2;
                player.SendMessage("Lucky force push!");
            }

            _.PlaySound("v_imp_frcpush");
            _.ApplyEffectToObject(DURATION_TYPE_INSTANT, _.EffectDamage(damage, DAMAGE_TYPE_POSITIVE), target);
            _.ApplyEffectToObject(DURATION_TYPE_TEMPORARY, _.EffectKnockdown(), target, length);
            CombatService.AddTemporaryForceDefense(target.Object, ForceAbilityType.Light);
        }
示例#15
0
        private static void OnModuleNWNXChat()
        {
            NWPlayer sender          = Object.OBJECT_SELF;
            string   originalMessage = NWNXChat.GetMessage().Trim();

            if (!CanHandleChat(sender, originalMessage))
            {
                return;
            }

            var split = originalMessage.Split(' ').ToList();

            // Commands with no arguments won't be split, so if we didn't split anything then add the command to the split list manually.
            if (split.Count <= 0)
            {
                split.Add(originalMessage);
            }

            split[0] = split[0].ToLower();
            string command = split[0].Substring(1, split[0].Length - 1);

            split.RemoveAt(0);

            NWNXChat.SkipMessage();

            if (!IsChatCommandRegistered(command))
            {
                sender.SendMessage(ColorTokenService.Red("Invalid chat command. Use '/help' to get a list of available commands."));
                return;
            }

            IChatCommand chatCommand = GetChatCommandHandler(command);
            string       args        = string.Join(" ", split);

            if (!chatCommand.RequiresTarget)
            {
                ProcessChatCommand(chatCommand, sender, null, null, args);
            }
            else
            {
                string error = chatCommand.ValidateArguments(sender, split.ToArray());
                if (!string.IsNullOrWhiteSpace(error))
                {
                    sender.SendMessage(error);
                    return;
                }

                sender.SetLocalString("CHAT_COMMAND", command);
                sender.SetLocalString("CHAT_COMMAND_ARGS", args);
                sender.SendMessage("Please use your 'Chat Command Targeter' feat to select the target of this chat command.");

                if (_.GetHasFeat((int)CustomFeatType.ChatCommandTargeter, sender) == FALSE || sender.IsDM)
                {
                    NWNXCreature.AddFeatByLevel(sender, (int)CustomFeatType.ChatCommandTargeter, 1);

                    if (sender.IsDM)
                    {
                        var qbs = NWNXPlayer.GetQuickBarSlot(sender, 11);
                        if (qbs.ObjectType == QuickBarSlotType.Empty)
                        {
                            NWNXPlayer.SetQuickBarSlot(sender, 11, NWNXPlayerQuickBarSlot.UseFeat((int)CustomFeatType.ChatCommandTargeter));
                        }
                    }
                }
            }
        }
示例#16
0
        public void DoAction(NWPlayer user, NWObject target, NWLocation targetLocation, params string[] args)
        {
            user.SendMessage("======================================================");
            user.SendMessage("PlayerDialogs: " + AppCache.PlayerDialogs.Count);
            user.SendMessage("DialogFilesInUse: " + AppCache.DialogFilesInUse.Count);
            user.SendMessage("EffectTicks: " + AppCache.EffectTicks.Count);
            user.SendMessage("CreatureSkillRegistrations: " + AppCache.CreatureSkillRegistrations.Count);
            user.SendMessage("NPCEffects: " + AppCache.NPCEffects.Count);
            user.SendMessage("UnregisterProcessingEvents: " + AppCache.UnregisterProcessingEvents.Count);
            user.SendMessage("NPCEnmityTables: " + AppCache.NPCEnmityTables.Count);
            user.SendMessage("CustomObjectData: " + AppCache.CustomObjectData.Count);
            user.SendMessage("AreaSpawns: " + AppCache.AreaSpawns.Count);
            user.SendMessage("VisibilityObjects: " + AppCache.VisibilityObjects.Count);
            user.SendMessage("PCEffectsForRemoval: " + AppCache.PCEffectsForRemoval.Count);
            user.SendMessage("======================================================");
            long memoryInUse = GC.GetTotalMemory(true);

            user.SendMessage("Memory In Use = " + memoryInUse);
        }
示例#17
0
        public void Main()
        {
            NWPlayer    oPC           = (_.GetLastDisturbed());
            NWItem      item          = (_.GetInventoryDisturbItem());
            NWPlaceable container     = (NWGameObject.OBJECT_SELF);
            int         disturbType   = _.GetInventoryDisturbType();
            var         structureID   = new Guid(container.GetLocalString("PC_BASE_STRUCTURE_ID"));
            var         structure     = DataService.PCBaseStructure.GetByID(structureID);
            var         baseStructure = DataService.BaseStructure.GetByID(structure.BaseStructureID);
            int         itemLimit     = baseStructure.Storage + structure.StructureBonus;

            int    itemCount  = container.InventoryItems.Count();
            string itemResref = item.Resref;

            if (disturbType == _.INVENTORY_DISTURB_TYPE_ADDED)
            {
                if (_.GetHasInventory(item) == _.TRUE)
                {
                    item.SetLocalInt("RETURNING_ITEM", _.TRUE);
                    ItemService.ReturnItem(oPC, item);
                    oPC.SendMessage(ColorTokenService.Red("Containers cannot currently be stored inside banks."));
                    return;
                }

                if (itemCount > itemLimit)
                {
                    ItemService.ReturnItem(oPC, item);
                    oPC.SendMessage(ColorTokenService.Red("No more items can be placed inside."));
                }
                else if (item.BaseItemType == _.BASE_ITEM_GOLD)
                {
                    ItemService.ReturnItem(oPC, item);
                    oPC.SendMessage(ColorTokenService.Red("Credits cannot be placed inside."));
                }
                else
                {
                    PCBaseStructureItem itemEntity = new PCBaseStructureItem
                    {
                        ItemName          = item.Name,
                        ItemResref        = itemResref,
                        ItemTag           = item.Tag,
                        PCBaseStructureID = structureID,
                        ItemGlobalID      = item.GlobalID.ToString(),
                        ItemObject        = SerializationService.Serialize(item)
                    };
                    DataService.SubmitDataChange(itemEntity, DatabaseActionType.Insert);
                    MessageHub.Instance.Publish(new OnStoreStructureItem(oPC, itemEntity));
                }
            }
            else if (disturbType == _.INVENTORY_DISTURB_TYPE_REMOVED)
            {
                if (item.GetLocalInt("RETURNING_ITEM") == _.TRUE)
                {
                    item.DeleteLocalInt("RETURNING_ITEM");
                }
                else
                {
                    var dbItem = DataService.PCBaseStructureItem.GetByItemGlobalID(item.GlobalID.ToString());
                    DataService.SubmitDataChange(dbItem, DatabaseActionType.Delete);
                    MessageHub.Instance.Publish(new OnRemoveStructureItem(oPC, dbItem));
                }
            }

            oPC.SendMessage(ColorTokenService.White("Item Limit: " + itemCount + " / ") + ColorTokenService.Red(itemLimit.ToString()));
        }
示例#18
0
        public override void DoAction(NWPlayer player, string pageName, int responseID)
        {
            PlayerDialog    dialog      = DialogService.LoadPlayerDialog(GetPC().GlobalID);
            Guid            structureID = new Guid(_.GetLocalString(player.Area, "PC_BASE_STRUCTURE_ID"));
            PCBaseStructure structure   = DataService.PCBaseStructure.GetByID(structureID);
            PCBase          pcBase      = DataService.PCBase.GetByID(structure.PCBaseID);

            DialogPage     page     = dialog.GetPageByName(pageName);
            DialogResponse response = page.Responses[responseID - 1];

            bool carefulPilot = PerkService.GetCreaturePerkLevel(player, PerkType.CarefulPilot) > 0;

            if (pageName == "MainPage")
            {
                // The number of dialog options available can vary.  So query based on the actual text of the response.
                if (response.Text == "Land")
                {
                    ChangePage("LandingDestPage");
                }
                else if (response.Text == "Pilot Ship")
                {
                    SpaceService.CreateShipInSpace(player.Area); // In case we logged in here.
                    SpaceService.DoFlyShip(GetPC(), GetPC().Area);
                    EndConversation();
                }
                else if (response.Text == "Hyperspace Jump")
                {
                    // Build the list of destinations.
                    ChangePage("HyperDestPage");
                }
                else if (response.Text == "Take Off")
                {
                    // Check fuel
                    if (pcBase.Fuel < 1)
                    {
                        GetPC().SendMessage("You don't have enough fuel! You need 1 fuel to take off.");
                        dialog.ResetPage();
                    }
                    else
                    {
                        // Fuel is good - we have liftoff.
                        if (!SpaceService.DoPilotingSkillCheck(GetPC(), 2, carefulPilot))
                        {
                            // Failed our skill check.  Deduct fuel but don't do anything else.
                            GetPC().FloatingText("The ship shudders a bit, but your awkwardness on the throttle shows, and it doesn't make it off the dock.  Try again.");
                            pcBase.Fuel -= 1;
                            DataService.SubmitDataChange(pcBase, DatabaseActionType.Update);
                            return;
                        }

                        EndConversation();

                        // Save details of the current dock for later.
                        Guid            shipPCBaseID = new Guid(pcBase.ShipLocation);
                        PCBaseStructure dock         = DataService.PCBaseStructure.GetByIDOrDefault(shipPCBaseID);

                        pcBase.Fuel        -= 1;
                        pcBase.DateRentDue  = DateTime.UtcNow.AddDays(99);
                        pcBase.ShipLocation = SpaceService.GetPlanetFromLocation(pcBase.ShipLocation) + " - Orbit";
                        DataService.SubmitDataChange(pcBase, DatabaseActionType.Update);

                        SpaceService.CreateShipInSpace(player.Area);

                        // Give the impression of movement
                        foreach (var creature in player.Area.Objects)
                        {
                            if (creature.IsPC || creature.IsDM)
                            {
                                _.FloatingTextStringOnCreature("The ship is taking off", creature);
                            }
                        }

                        _.ApplyEffectToObject(DurationType.Instant, _.EffectVisualEffect(VisualEffect.Vfx_Fnf_Screen_Shake), player);

                        // Clean up the base structure, if we were in a PC dock not public starport.
                        // Get a reference to our placeable (and door), and delete them with some VFX.
                        if (dock != null)
                        {
                            PCBase dockBase = DataService.PCBase.GetByID(dock.PCBaseID);

                            IEnumerable <NWArea> areas = NWModule.Get().Areas;
                            NWArea landingArea         = new NWArea(_.GetFirstArea());

                            foreach (var area in areas)
                            {
                                if (_.GetResRef(area) == dockBase.AreaResref)
                                {
                                    landingArea = area;
                                }
                            }

                            List <AreaStructure> areaStructures = landingArea.Data["BASE_SERVICE_STRUCTURES"];
                            foreach (var plc in areaStructures)
                            {
                                if (plc.PCBaseStructureID == dock.ID)
                                {
                                    // Found our dock.  Clear its variable and play some VFX.
                                    plc.Structure.SetLocalInt("DOCKED_STARSHIP", 0);
                                    DoDustClouds(plc.Structure.Location);
                                    _.ApplyEffectToObject(DurationType.Instant, _.EffectVisualEffect(VisualEffect.Vfx_Fnf_Screen_Shake), plc.Structure);
                                }
                                else if (plc.PCBaseStructureID == structure.ID)
                                {
                                    // found either our ship or our entrance (both are saved with our structure ID).  Delete them.
                                    // Dp NOT remove the PC base structure object from the database.  We still need that.
                                    plc.Structure.Destroy();
                                }
                            }
                        }
                    }
                }
                else if (response.Text == "Access Fuel Bay")
                {
                    OpenFuelBay(false);
                    EndConversation();
                }
                else if (response.Text == "Access Stronidium Bay")
                {
                    OpenFuelBay(true);
                    EndConversation();
                }
                else if (response.Text == "Access Resource Bay")
                {
                    NWPlaceable bay = SpaceService.GetCargoBay(player.Area, GetPC());
                    if (bay != null)
                    {
                        GetPC().AssignCommand(() => _.ActionInteractObject(bay.Object));
                    }
                    EndConversation();
                }
                else if (response.Text == "Export Starcharts")
                {
                    NWItem item = _.CreateItemOnObject("starcharts", player, 1, _.Random(10000).ToString());

                    // Initialise the list, in case it hasn't been populated yet.
                    SpaceService.GetHyperspaceDestinationList(pcBase);

                    item.SetLocalInt("Starcharts", (int)pcBase.Starcharts);
                }
            }
            else if (pageName == "HyperDestPage")
            {
                // Check fuel
                if (pcBase.Fuel < 50)
                {
                    GetPC().SendMessage("You don't have enough fuel! You need 50 fuel to make a hyperspace jump.");
                    dialog.ResetPage();
                }
                else
                {
                    // Fuel is good - make the jump
                    if (!SpaceService.DoPilotingSkillCheck(GetPC(), 13, carefulPilot))
                    {
                        // Failed our skill check.  Deduct fuel but don't do anything else.
                        GetPC().FloatingText("Jump failed!  You forgot to whatsit the thingummyjig.");
                        pcBase.Fuel -= 50;
                        DataService.SubmitDataChange(pcBase, DatabaseActionType.Update);
                        EndConversation();
                        return;
                    }

                    // Move the ship out of the old orbit.
                    SpaceService.RemoveShipInSpace(player.Area);

                    // Fade to black for hyperspace.
                    EndConversation();
                    pcBase.Fuel        -= 50;
                    pcBase.ShipLocation = response.Text + " - Orbit";
                    DataService.SubmitDataChange(pcBase, DatabaseActionType.Update);

                    // Put the ship in its new orbit.
                    SpaceService.CreateShipInSpace(player.Area);

                    // Give the impression of movement - would be great to have the actual hyperspace jump graphics here.
                    foreach (var creature in player.Area.Objects)
                    {
                        if (creature.IsPC || creature.IsDM)
                        {
                            _.FloatingTextStringOnCreature("Making a hyperspace jump!", creature);
                            _.FadeToBlack(creature, 0.5f);
                            _.DelayCommand(1.0f, () => { _.FadeFromBlack(creature, 0.5f); });
                        }
                    }
                }
            }
            else if (pageName == "LandingDestPage")
            {
                // Skill check.
                if (!SpaceService.DoPilotingSkillCheck(GetPC(), 5, carefulPilot))
                {
                    // Failed our skill check.  Land anyway but burn more fuel.
                    if (pcBase.Fuel > 0)
                    {
                        GetPC().FloatingText("You overshoot the landing spot, burning extra fuel getting your ship into position.");
                        pcBase.Fuel -= 1;
                        DataService.SubmitDataChange(pcBase, DatabaseActionType.Update);
                    }
                }

                // Get the response, then find the structure ID.
                Guid dockStructureID = dialog.CustomData["LAND_" + response.Text];

                // This could be a public startport ID or a private dock base structure ID.
                Starport starport = DataService.Starport.GetByStarportIDOrDefault(dockStructureID);
                if (starport != null)
                {
                    // We have a public starport.
                    if (player.Gold < starport.Cost)
                    {
                        player.SendMessage("You do not have enough credits to land here.");
                        return;
                    }
                    else
                    {
                        _.TakeGoldFromCreature(starport.Cost, player, true);

                        // Land.
                        pcBase.ShipLocation = starport.StarportID.ToString();
                        pcBase.DateRentDue  = DateTime.UtcNow.AddDays(1);
                        DataService.SubmitDataChange(pcBase, DatabaseActionType.Update);

                        // Notify PC.
                        player.SendMessage("You have paid your first day's berthing fees. Use the Base Management System to extend your lease if you plan to stay longer, or your ship will be impounded.");

                        EndConversation();
                    }
                }
                else
                {
                    LoggingService.Trace(TraceComponent.Space, "Landing in PC base dock, ID: " + dockStructureID.ToString());
                    PCBaseStructure dock = DataService.PCBaseStructure.GetByIDOrDefault(dockStructureID);

                    if (dock == null)
                    {
                        player.SendMessage("ERROR: Could not find landing dock by ID.  Please report this.");
                        LoggingService.Trace(TraceComponent.Space, "Could not find landing dock ID " + dockStructureID.ToString());
                        return;
                    }

                    NWPlaceable plc = BaseService.FindPlaceableFromStructureID(dock.ID.ToString());

                    if (plc == null)
                    {
                        LoggingService.Trace(TraceComponent.Space, "Failed to find dock placeable.");
                        player.SendMessage("ERROR: Could not find landing dock placeable.  Please report this.");
                        return;
                    }

                    LoggingService.Trace(TraceComponent.Space, "Found dock, landing ship.");

                    // We've found our dock. Update our record of where the ship's exterior should spawn.
                    NWLocation loc = plc.Location;

                    structure.LocationX           = loc.X;
                    structure.LocationY           = loc.Y;
                    structure.LocationZ           = loc.Z;
                    structure.LocationOrientation = _.GetFacingFromLocation(loc);

                    DataService.SubmitDataChange(structure, DatabaseActionType.Update);

                    // And update the base to mark the parent dock as the location.
                    pcBase.ShipLocation = dock.ID.ToString();
                    DataService.SubmitDataChange(pcBase, DatabaseActionType.Update);

                    // Now use the Base Service to spawn the ship exterior.
                    BaseService.SpawnStructure(plc.Area, structure.ID);

                    // Mark the dock as occupied.
                    plc.SetLocalInt("DOCKED_STARSHIP", 1);

                    // Notify PCs in the landing area.
                    foreach (var creature in plc.Area.Objects)
                    {
                        if (creature.IsPC || creature.IsDM)
                        {
                            _.FloatingTextStringOnCreature("A ship has just landed!", creature);
                        }
                    }

                    // And shake the screen, because stuff.
                    _.ApplyEffectAtLocation(DurationType.Instant, _.EffectVisualEffect(VisualEffect.Vfx_Fnf_Screen_Shake), loc);
                    DoDustClouds(loc);
                }

                // We're landing.  Make sure any pilot or gunner get out of flight mode.
                SpaceService.LandCrew(player.Area);

                // If we are still here, we landed successfully.  Shake the screen about and notify PCs on the ship.
                // Give the impression of movement
                foreach (var creature in player.Area.Objects)
                {
                    if (creature.IsPC || creature.IsDM)
                    {
                        _.FloatingTextStringOnCreature("The ship is landing.", creature);
                    }
                }

                _.ApplyEffectToObject(DurationType.Instant, _.EffectVisualEffect(VisualEffect.Vfx_Fnf_Screen_Shake), player);
                SpaceService.RemoveShipInSpace(player.Area);

                EndConversation();
            }
        }
示例#19
0
        public void OnImpact(NWPlayer player, NWObject target, int level)
        {
            var effectiveStats = _playerStat.GetPlayerItemEffectiveStats(player);
            int lightBonus     = effectiveStats.LightAbility;
            int amount;
            int length;
            int dotAmount;
            int min          = 1;
            int wisdom       = player.WisdomModifier;
            int intelligence = player.IntelligenceModifier;

            min += lightBonus / 3 + wisdom / 2 + intelligence / 3;

            switch (level)
            {
            case 1:
                amount    = _random.D6(2, min);
                length    = 0;
                dotAmount = 0;
                break;

            case 2:
                amount    = _random.D6(2, min);
                length    = 6;
                dotAmount = 1;
                break;

            case 3:
                amount    = _random.D12(2, min);
                length    = 6;
                dotAmount = 1;
                break;

            case 4:
                amount    = _random.D12(2, min);
                length    = 12;
                dotAmount = 1;
                break;

            case 5:
                amount    = _random.D12(2, min);
                length    = 6;
                dotAmount = 2;
                break;

            case 6:
                amount    = _random.D12(2, min);
                length    = 12;
                dotAmount = 2;
                break;

            case 7:
                amount    = _random.D12(3, min);
                length    = 12;
                dotAmount = 2;
                break;

            case 8:
                amount    = _random.D12(3, min);
                length    = 6;
                dotAmount = 4;
                break;

            case 9:
                amount    = _random.D12(4, min);
                length    = 6;
                dotAmount = 4;
                break;

            case 10:
                amount    = _random.D12(4, min);
                length    = 12;
                dotAmount = 4;
                break;

            case 11:     // Only attainable with background bonus
                amount    = _random.D12(5, min);
                length    = 12;
                dotAmount = 4;
                break;

            default: return;
            }

            int luck = _perk.GetPCPerkLevel(player, PerkType.Lucky) + effectiveStats.Luck;

            if (_random.Random(100) + 1 <= luck)
            {
                length = length * 2;
                player.SendMessage("Lucky force breach!");
            }

            Effect damage = _.EffectDamage(amount);

            _.ApplyEffectToObject(DURATION_TYPE_INSTANT, damage, target.Object);

            if (length > 0.0f && dotAmount > 0)
            {
                _customEffect.ApplyCustomEffect(player, target.Object, CustomEffectType.ForceBreach, length, level, null);
            }

            _skill.RegisterPCToAllCombatTargetsForSkill(player, SkillType.LightSideAbilities, target.Object);

            Effect vfx = _.EffectVisualEffect(VFX_IMP_DOMINATE_S);

            _.ApplyEffectToObject(DURATION_TYPE_INSTANT, vfx, target.Object);
        }
示例#20
0
        public override PlayerDialog SetUp(NWPlayer player)
        {
            PlayerDialog dialog = new PlayerDialog("MainPage");

            string structureID = _.GetLocalString(_.GetArea(player), "PC_BASE_STRUCTURE_ID");

            if (string.IsNullOrWhiteSpace(structureID))
            {
                player.SendMessage("Base structure ID not found on area.  Please report this problem.");
                return(null);
            }

            Guid            pcBaseStructureID = new Guid(structureID);
            PCBaseStructure structure         = DataService.PCBaseStructure.GetByID(pcBaseStructureID);
            PCBase          pcBase            = DataService.PCBase.GetByID(structure.PCBaseID);

            bool bSpace = SpaceService.IsLocationSpace(pcBase.ShipLocation);

            List <string> options = new List <string>();

            if (bSpace && BasePermissionService.HasStructurePermission(player, structure.ID, StructurePermission.CanFlyStarship))
            {
                // See if we are near enough to the planet to land.
                if (SpaceService.CanLandOnPlanet(player.Area))
                {
                    options.Add("Land");
                }

                options.Add("Pilot Ship");
                options.Add("Hyperspace Jump");
            }
            else if (BasePermissionService.HasStructurePermission(player, structure.ID, StructurePermission.CanFlyStarship))
            {
                options.Add("Take Off");
            }

            if (!bSpace && BasePermissionService.HasBasePermission(player, structure.PCBaseID, BasePermission.CanManageBaseFuel))
            {
                options.Add("Access Fuel Bay");
                options.Add("Access Stronidium Bay");
            }

            if (BasePermissionService.HasBasePermission(player, structure.PCBaseID, BasePermission.CanAccessStructureInventory))
            {
                if (!bSpace)
                {
                    options.Add("Access Resource Bay");
                }
                options.Add("Export Starcharts");
            }

            DialogPage mainPage = new DialogPage("", options.ToArray());

            dialog.AddPage("MainPage", mainPage);

            // Hyperspace destinations.
            string[]   responses       = SpaceService.GetHyperspaceDestinationList(pcBase);
            DialogPage destinationPage = new DialogPage("Please select a destination to fly to.", responses);

            dialog.AddPage("HyperDestPage", destinationPage);

            // Landing destinations.
            Hashtable     landingspots = SpaceService.GetLandingDestinationList(player, pcBase);
            List <String> responseList = landingspots.Keys.Cast <String>().ToList();
            DialogPage    landingPage  = new DialogPage("Where do you want to land?", responseList.ToArray());

            dialog.AddPage("LandingDestPage", landingPage);

            // Save off the landing responses in CustomData.  This ensures we can access the structure IDs later.
            foreach (var key in landingspots.Keys)
            {
                dialog.CustomData.Add("LAND_" + key, landingspots[key]);
            }

            return(dialog);
        }
示例#21
0
        public void OnImpact(NWPlayer player, NWObject target, int perkLevel, int spellFeatID)
        {
            float       recoveryPercent;
            int         basePotency;
            const float Tier1Modifier = 1;
            const float Tier2Modifier = 2;
            const float Tier3Modifier = 0;
            const float Tier4Modifier = 0;

            switch (perkLevel)
            {
            case 1:
                basePotency     = 10;
                recoveryPercent = 0.2f;
                break;

            case 2:
                basePotency     = 15;
                recoveryPercent = 0.2f;
                break;

            case 3:
                basePotency     = 20;
                recoveryPercent = 0.4f;
                break;

            case 4:
                basePotency     = 25;
                recoveryPercent = 0.4f;
                break;

            case 5:
                basePotency     = 30;
                recoveryPercent = 0.5f;
                break;

            default: return;
            }

            var effectiveStats = PlayerStatService.GetPlayerItemEffectiveStats(player);
            int luck           = PerkService.GetPCPerkLevel(player, PerkType.Lucky) + effectiveStats.Luck;

            if (RandomService.Random(100) + 1 <= luck)
            {
                recoveryPercent = 1.0f;
                player.SendMessage("Lucky drain life!");
            }

            var calc = CombatService.CalculateForceDamage(
                player,
                target.Object,
                ForceAbilityType.Dark,
                basePotency,
                Tier1Modifier,
                Tier2Modifier,
                Tier3Modifier,
                Tier4Modifier);

            _.AssignCommand(player, () =>
            {
                int heal = (int)(calc.Damage * recoveryPercent);
                if (heal > target.CurrentHP)
                {
                    heal = target.CurrentHP;
                }

                _.ApplyEffectToObject(DURATION_TYPE_INSTANT, _.EffectDamage(calc.Damage), target);
                _.ApplyEffectToObject(DURATION_TYPE_INSTANT, _.EffectHeal(heal), player);
                _.ApplyEffectToObject(DURATION_TYPE_TEMPORARY, _.EffectVisualEffect(VFX_BEAM_MIND), target, 1.0f);
            });

            _.PlaySound("v_pro_drain");
            SkillService.RegisterPCToAllCombatTargetsForSkill(player, SkillType.ForceCombat, target.Object);
            CombatService.AddTemporaryForceDefense(target.Object, ForceAbilityType.Dark);
        }
示例#22
0
文件: Quest.cs 项目: zunath/SWLOR_NWN
        public void Advance(NWPlayer player, NWObject questSource)
        {
            if (!player.IsPlayer)
            {
                return;
            }

            // Retrieve the player's current quest state.
            PCQuestStatus questStatus = DataService.PCQuestStatus.GetByPlayerAndQuestIDOrDefault(player.GlobalID, QuestID);

            // Can't find a state? Notify the player they haven't accepted the quest.
            if (questStatus == null)
            {
                player.SendMessage("You have not accepted this quest yet.");
                return;
            }

            // If this quest has already been completed, exit early.
            // This is used in case a module builder incorrectly configures a quest.
            // We don't want to risk giving duplicate rewards.
            if (questStatus.CompletionDate != null)
            {
                return;
            }

            var currentState = GetState(questStatus.QuestState);
            var lastState    = GetStates().Last();

            // If this is the last state, the assumption is that it's time to complete the quest.
            if (currentState == lastState)
            {
                RequestRewardSelectionFromPC(player, questSource);
            }
            else
            {
                // Progress player's quest status to the next state.
                questStatus.QuestState++;
                var nextState = GetState(questStatus.QuestState);

                // Update the player's journal
                AddJournalQuestEntry(JournalTag, questStatus.QuestState, player, false);

                // Notify the player they've progressed.
                player.SendMessage("Objective for quest '" + Name + "' complete! Check your journal for information on the next objective.");

                // Submit all of these changes to the cache/DB.
                DataService.SubmitDataChange(questStatus, DatabaseActionType.Update);

                // Create any extended data entries for the next state of the quest.
                foreach (var objective in nextState.GetObjectives())
                {
                    objective.Initialize(player, QuestID);
                }

                // Run any quest-specific code.
                _onAdvance?.Invoke(player, questSource, questStatus.QuestState);

                // Notify to subscribers that the player has advanced to the next state of the quest.
                MessageHub.Instance.Publish(new OnQuestAdvanced(player, QuestID, questStatus.QuestState));
            }
        }
示例#23
0
        /// <summary>
        /// Displays the public CD key of the user.
        /// </summary>
        /// <param name="user"></param>
        /// <param name="target"></param>
        /// <param name="targetLocation"></param>
        /// <param name="args"></param>
        public void DoAction(NWPlayer user, NWObject target, NWLocation targetLocation, params string[] args)
        {
            string cdKey = _.GetPCPublicCDKey(user);

            user.SendMessage("Your public CD Key is: " + cdKey);
        }
示例#24
0
        public void Main()
        {
            NWPlayer oPC = GetLastUsedBy();

            if (GetIsInCombat(oPC) == true)
            {
                SendMessageToPC(oPC, "You are in combat.");
                return;
            }

            NWPlaceable self                  = OBJECT_SELF;
            string      destination           = self.GetLocalString("DESTINATION");
            var         visualEffectID        = self.GetLocalInt("VISUAL_EFFECT") > 0 ? (VisualEffect)self.GetLocalInt("VISUAL_EFFECT") : VisualEffect.Invalid;
            int         keyItemID             = self.GetLocalInt("KEY_ITEM_ID");
            string      missingKeyItemMessage = self.GetLocalString("MISSING_KEY_ITEM_MESSAGE");
            bool        isInstance            = GetLocalBool(self, "INSTANCE") == true;
            bool        personalInstanceOnly  = GetLocalBool(self, "PERSONAL_INSTANCE_ONLY");

            if (keyItemID > 0)
            {
                if (!KeyItemService.PlayerHasKeyItem(oPC, keyItemID))
                {
                    if (!string.IsNullOrWhiteSpace(missingKeyItemMessage))
                    {
                        oPC.SendMessage(missingKeyItemMessage);
                    }
                    else
                    {
                        oPC.SendMessage("You don't have the necessary key item to access that object.");
                    }

                    return;
                }
            }

            if (visualEffectID > 0)
            {
                ApplyEffectToObject(DurationType.Instant, EffectVisualEffect(visualEffectID), oPC.Object);
            }

            NWObject   entranceWP = GetWaypointByTag(destination);
            NWLocation location   = GetLocation(entranceWP);

            if (!entranceWP.IsValid)
            {
                oPC.SendMessage("Cannot locate entrance waypoint. Inform an admin.");
                return;
            }

            if (isInstance)
            {
                var members = oPC.PartyMembers.Where(x => x.Area.GetLocalString("ORIGINAL_RESREF") == entranceWP.Area.Resref).ToList();

                // A party member is in an instance of this type already.
                // Prompt player to select which instance to enter.
                if (members.Count >= 1 && !personalInstanceOnly)
                {
                    oPC.SetLocalString("INSTANCE_RESREF", entranceWP.Area.Resref);
                    oPC.SetLocalString("INSTANCE_DESTINATION_TAG", destination);
                    DialogService.StartConversation(oPC, self, "InstanceSelection");
                    return;
                }

                // Otherwise no instance exists yet or this instance only allows one player. Make a new one for this player.
                NWArea instance = AreaService.CreateAreaInstance(oPC, entranceWP.Area.Resref, entranceWP.Area.Name, destination);
                location = instance.GetLocalLocation("INSTANCE_ENTRANCE");
                PlayerService.SaveLocation(oPC);
            }

            oPC.AssignCommand(() =>
            {
                ActionJumpToLocation(location);
            });
        }
示例#25
0
        public void FinishActionItem(IActionItem actionItem, NWPlayer user, NWItem item, NWObject target, Location targetLocation, Vector userStartPosition, CustomData customData)
        {
            user.IsBusy = false;

            Vector userPosition = user.Position;

            if (userPosition.m_X != userStartPosition.m_X ||
                userPosition.m_Y != userStartPosition.m_Y ||
                userPosition.m_Z != userStartPosition.m_Z)
            {
                user.SendMessage("You move and interrupt your action.");
                return;
            }

            float maxDistance = actionItem.MaxDistance(user, item, target, targetLocation);

            if (maxDistance > 0.0f)
            {
                if (target.IsValid &&
                    (_.GetDistanceBetween(user.Object, target.Object) > maxDistance ||
                     user.Area.Resref != target.Area.Resref))
                {
                    user.SendMessage("Your target is too far away.");
                    return;
                }
                else if (!target.IsValid &&
                         (_.GetDistanceBetweenLocations(user.Location, targetLocation) > maxDistance ||
                          user.Area.Resref != ((NWArea)_.GetAreaFromLocation(targetLocation)).Resref))
                {
                    user.SendMessage("That location is too far away.");
                    return;
                }
            }

            if (!target.IsValid && !actionItem.AllowLocationTarget())
            {
                user.SendMessage("Unable to locate target.");
                return;
            }

            string invalidTargetMessage = actionItem.IsValidTarget(user, item, target, targetLocation);

            if (!string.IsNullOrWhiteSpace(invalidTargetMessage))
            {
                user.SendMessage(invalidTargetMessage);
                return;
            }

            actionItem.ApplyEffects(user, item, target, targetLocation, customData);

            if (actionItem.ReducesItemCharge(user, item, target, targetLocation, customData))
            {
                if (item.Charges > 0)
                {
                    item.ReduceCharges();
                }
                else
                {
                    item.Destroy();
                }
            }
        }
示例#26
0
        private void HandleDistributeRPXPResponse(int responseID)
        {
            NWPlayer player   = GetPC();
            Player   dbPlayer = DataService.Player.GetByID(player.GlobalID);
            Model    vm       = GetDialogCustomData <Model>();

            int rpXpToDistribute = dbPlayer.RoleplayXP;

            PCSkill pcSkill = SkillService.GetPCSkill(player, vm.SelectedSkillID);
            Skill   skill   = SkillService.GetSkill(vm.SelectedSkillID);
            // Get all player skills and then sum them up by the rank.
            int totalSkillCount = DataService.PCSkill
                                  .GetAllByPlayerID(player.GlobalID)
                                  .Where(x => DataService.Skill.GetByID(x.SkillID).ContributesToSkillCap)
                                  .Sum(s => s.Rank);
            int totalSkillXpToMaxRank = 0;

            //totalSkillCount < SkillService.SkillCap
            for (int x = pcSkill.Rank + 1; x < skill.MaxRank; x++)
            {
                int tempValue;
                if (SkillService.SkillXPRequirements.TryGetValue(x, out tempValue))
                {
                    totalSkillXpToMaxRank += tempValue;
                }
            }

            switch (responseID)
            {
            case 1:     // Select All RP XP
                vm.RPXPDistributing = totalSkillXpToMaxRank;
                break;

            case 2:     // Increase by 1000
                vm.RPXPDistributing += 1000;
                break;

            case 3:     // Increase by 100
                vm.RPXPDistributing += 100;
                break;

            case 4:     // Increase by 10
                vm.RPXPDistributing += 10;
                break;

            case 5:     // Increase by 1
                vm.RPXPDistributing += 1;
                break;

            case 6:     // Decrease by 1000
                vm.RPXPDistributing -= 1000;
                break;

            case 7:     // Decrease by 100
                vm.RPXPDistributing -= 100;
                break;

            case 8:     // Decrease by 10
                vm.RPXPDistributing -= 10;
                break;

            case 9:     // Decrease by 1
                vm.RPXPDistributing -= 1;
                break;

            case 10:     // Distribute Roleplay XP

                // Make sure the player specified how much they want to distribute.
                if (vm.RPXPDistributing <= 0)
                {
                    player.SendMessage("Please specify how much RP XP you'd like to distribute into this skill.");
                    vm.IsConfirming = false;
                }
                else if (vm.RPXPDistributing > totalSkillXpToMaxRank)
                {
                    player.SendMessage("Please lower your distribution amount, current max for this skill is " + totalSkillXpToMaxRank + ".");
                    vm.IsConfirming = false;
                }
                else
                {
                    if (vm.IsConfirming)
                    {
                        // Give the distributed XP to a particular skill.
                        // We disable residency bonuses, DM bonuses, and skill penalties during this distribution because
                        // those are calculated when we give the player RP XP.
                        SkillService.GiveSkillXP(player, vm.SelectedSkillID, vm.RPXPDistributing, false, false);

                        dbPlayer             = DataService.Player.GetByID(player.GlobalID);
                        dbPlayer.RoleplayXP -= vm.RPXPDistributing;
                        DataService.SubmitDataChange(dbPlayer, DatabaseActionType.Update);
                        vm.IsConfirming     = false;
                        vm.RPXPDistributing = 0;
                    }
                    else
                    {
                        vm.IsConfirming = true;
                    }
                }
                break;
            }

            if (vm.RPXPDistributing > dbPlayer.RoleplayXP)
            {
                vm.RPXPDistributing = dbPlayer.RoleplayXP;
            }
            else if (vm.RPXPDistributing < 0)
            {
                vm.RPXPDistributing = 0;
            }

            LoadDistributeRPXPPage();
        }
示例#27
0
        private static void OnModuleNWNXChat()
        {
            ChatChannelType channel = (ChatChannelType)NWNXChat.GetChannel();

            // So we're going to play with a couple of channels here.

            // - PlayerTalk, PlayerWhisper, PlayerParty, and PlayerShout are all IC channels. These channels
            //   are subject to emote colouring and language translation. (see below for more info).
            // - PlayerParty is an IC channel with special behaviour. Those outside of the party but within
            //   range may listen in to the party chat. (see below for more information).
            // - PlayerShout sends a holocom message server-wide through the DMTell channel.
            // - PlayerDM echoes back the message received to the sender.

            bool inCharacterChat =
                channel == ChatChannelType.PlayerTalk ||
                channel == ChatChannelType.PlayerWhisper ||
                channel == ChatChannelType.PlayerParty ||
                channel == ChatChannelType.PlayerShout;

            bool messageToDm = channel == ChatChannelType.PlayerDM;

            if (!inCharacterChat && !messageToDm)
            {
                // We don't much care about traffic on the other channels.
                return;
            }

            NWObject sender  = NWNXChat.GetSender();
            string   message = NWNXChat.GetMessage().Trim();

            if (string.IsNullOrWhiteSpace(message))
            {
                // We can't handle empty messages, so skip it.
                return;
            }

            if (ChatCommandService.CanHandleChat(sender, message) ||
                BaseService.CanHandleChat(sender) ||
                CraftService.CanHandleChat(sender) ||
                MarketService.CanHandleChat(sender.Object) ||
                MessageBoardService.CanHandleChat(sender) ||
                ItemService.CanHandleChat(sender))
            {
                // This will be handled by other services, so just bail.
                return;
            }

            if (channel == ChatChannelType.PlayerDM)
            {
                // Simply echo the message back to the player.
                NWNXChat.SendMessage((int)ChatChannelType.ServerMessage, "(Sent to DM) " + message, sender, sender);
                return;
            }

            // At this point, every channel left is one we want to manually handle.
            NWNXChat.SkipMessage();

            // If this is a shout message, and the holonet is disabled, we disallow it.
            if (channel == ChatChannelType.PlayerShout && sender.IsPC &&
                sender.GetLocalInt("DISPLAY_HOLONET") == FALSE)
            {
                NWPlayer player = sender.Object;
                player.SendMessage("You have disabled the holonet and cannot send this message.");
                return;
            }

            List <ChatComponent> chatComponents;

            // Quick early out - if we start with "//" or "((", this is an OOC message.
            bool isOOC = false;

            if (message.Length >= 2 && (message.Substring(0, 2) == "//" || message.Substring(0, 2) == "(("))
            {
                ChatComponent component = new ChatComponent
                {
                    m_Text         = message,
                    m_CustomColour = true,
                    m_ColourRed    = 64,
                    m_ColourGreen  = 64,
                    m_ColourBlue   = 64,
                    m_Translatable = false
                };

                chatComponents = new List <ChatComponent> {
                    component
                };

                if (channel == ChatChannelType.PlayerShout)
                {
                    _.SendMessageToPC(sender, "Out-of-character messages cannot be sent on the Holonet.");
                    return;
                }

                isOOC = true;
            }
            else
            {
                if (EmoteStyleService.GetEmoteStyle(sender) == EmoteStyle.Regular)
                {
                    chatComponents = SplitMessageIntoComponents_Regular(message);
                }
                else
                {
                    chatComponents = SplitMessageIntoComponents_Novel(message);
                }

                // For any components with colour, set the emote colour.
                foreach (ChatComponent component in chatComponents)
                {
                    if (component.m_CustomColour)
                    {
                        component.m_ColourRed   = 0;
                        component.m_ColourGreen = 255;
                        component.m_ColourBlue  = 0;
                    }
                }
            }

            // Now, depending on the chat channel, we need to build a list of recipients.
            bool  needsAreaCheck = false;
            float distanceCheck  = 0.0f;

            // The sender always wants to see their own message.
            List <NWObject> recipients = new List <NWObject> {
                sender
            };

            // This is a server-wide holonet message (that receivers can toggle on or off).
            if (channel == ChatChannelType.PlayerShout)
            {
                recipients.AddRange(NWModule.Get().Players.Where(player => player.GetLocalInt("DISPLAY_HOLONET") == TRUE));
                recipients.AddRange(AppCache.ConnectedDMs);
            }
            // This is the normal party chat, plus everyone within 20 units of the sender.
            else if (channel == ChatChannelType.PlayerParty)
            {
                // Can an NPC use the playerparty channel? I feel this is safe ...
                NWPlayer player = sender.Object;
                recipients.AddRange(player.PartyMembers.Cast <NWObject>().Where(x => x != sender));
                recipients.AddRange(AppCache.ConnectedDMs);

                needsAreaCheck = true;
                distanceCheck  = 20.0f;
            }
            // Normal talk - 20 units.
            else if (channel == ChatChannelType.PlayerTalk)
            {
                needsAreaCheck = true;
                distanceCheck  = 20.0f;
            }
            // Whisper - 4 units.
            else if (channel == ChatChannelType.PlayerWhisper)
            {
                needsAreaCheck = true;
                distanceCheck  = 4.0f;
            }

            if (needsAreaCheck)
            {
                recipients.AddRange(sender.Area.Objects.Where(obj => obj.IsPC && _.GetDistanceBetween(sender, obj) <= distanceCheck));
                recipients.AddRange(AppCache.ConnectedDMs.Where(dm => dm.Area == sender.Area && _.GetDistanceBetween(sender, dm) <= distanceCheck));
            }

            // Now we have a list of who is going to actually receive a message, we need to modify
            // the message for each recipient then dispatch them.

            foreach (NWObject obj in recipients.Distinct())
            {
                // Generate the final message as perceived by obj.

                StringBuilder finalMessage = new StringBuilder();

                if (channel == ChatChannelType.PlayerShout)
                {
                    finalMessage.Append("[Holonet] ");
                }
                else if (channel == ChatChannelType.PlayerParty)
                {
                    finalMessage.Append("[Comms] ");

                    if (obj.IsDM)
                    {
                        // Convenience for DMs - append the party members.
                        finalMessage.Append("{ ");

                        int               count        = 0;
                        NWPlayer          player       = sender.Object;
                        List <NWCreature> partyMembers = player.PartyMembers.ToList();

                        foreach (NWCreature otherPlayer in partyMembers)
                        {
                            string name = otherPlayer.Name;
                            finalMessage.Append(name.Substring(0, Math.Min(name.Length, 10)));

                            ++count;

                            if (count >= 3)
                            {
                                finalMessage.Append(", ...");
                                break;
                            }
                            else if (count != partyMembers.Count)
                            {
                                finalMessage.Append(",");
                            }
                        }

                        finalMessage.Append(" } ");
                    }
                }

                SkillType language = LanguageService.GetActiveLanguage(sender);

                // Wookiees cannot speak any other language (but they can understand them).
                // Swap their language if they attempt to speak in any other language.
                CustomRaceType race = (CustomRaceType)_.GetRacialType(sender);
                if (race == CustomRaceType.Wookiee && language != SkillType.Shyriiwook)
                {
                    LanguageService.SetActiveLanguage(sender, SkillType.Shyriiwook);
                    language = SkillType.Shyriiwook;
                }

                int  colour = LanguageService.GetColour(language);
                byte r      = (byte)(colour >> 24 & 0xFF);
                byte g      = (byte)(colour >> 16 & 0xFF);
                byte b      = (byte)(colour >> 8 & 0xFF);

                if (language != SkillType.Basic)
                {
                    string languageName = LanguageService.GetName(language);
                    finalMessage.Append(ColorTokenService.Custom($"[{languageName}] ", r, g, b));
                }

                foreach (ChatComponent component in chatComponents)
                {
                    string text = component.m_Text;

                    if (component.m_Translatable && language != SkillType.Basic)
                    {
                        text = LanguageService.TranslateSnippetForListener(sender, obj.Object, language, component.m_Text);

                        if (colour != 0)
                        {
                            text = ColorTokenService.Custom(text, r, g, b);
                        }
                    }

                    if (component.m_CustomColour)
                    {
                        text = ColorTokenService.Custom(text, component.m_ColourRed, component.m_ColourGreen, component.m_ColourBlue);
                    }

                    finalMessage.Append(text);
                }

                // Dispatch the final message - method depends on the original chat channel.
                // - Shout and party is sent as DMTalk. We do this to get around the restriction that
                //   the PC needs to be in the same area for the normal talk channel.
                //   We could use the native channels for these but the [shout] or [party chat] labels look silly.
                // - Talk and whisper are sent as-is.

                ChatChannelType finalChannel = channel;

                if (channel == ChatChannelType.PlayerShout || channel == ChatChannelType.PlayerParty)
                {
                    finalChannel = ChatChannelType.DMTalk;
                }

                // There are a couple of colour overrides we want to use here.
                // - One for holonet (shout).
                // - One for comms (party chat).

                string finalMessageColoured = finalMessage.ToString();

                if (channel == ChatChannelType.PlayerShout)
                {
                    finalMessageColoured = ColorTokenService.Custom(finalMessageColoured, 0, 180, 255);
                }
                else if (channel == ChatChannelType.PlayerParty)
                {
                    finalMessageColoured = ColorTokenService.Orange(finalMessageColoured);
                }

                NWNXChat.SendMessage((int)finalChannel, finalMessageColoured, sender, obj);
            }

            MessageHub.Instance.Publish(new OnChatProcessed(sender, channel, isOOC));
        }
示例#28
0
        public void ApplyEffects(NWCreature user, NWItem modItem, NWObject target, Location targetLocation, CustomData customData)
        {
            NWPlayer player                = (user.Object);
            NWItem   targetItem            = (target.Object);
            ModSlots slots                 = _mod.GetModSlots(targetItem);
            CustomItemPropertyType modType = _mod.GetModType(modItem);
            int modID = modItem.GetLocalInt("RUNE_ID");

            string[] modArgs       = modItem.GetLocalString("RUNE_VALUE").Split(',');
            int      modLevel      = modItem.RecommendedLevel;
            int      levelIncrease = modItem.LevelIncrease;

            var dbMod = _data.Single <Data.Entity.Mod>(x => x.ID == modID && x.IsActive);

            App.ResolveByInterface <IMod>("Mod." + dbMod.Script, mod =>
            {
                mod.Apply(player, targetItem, modArgs);

                string description = mod.Description(player, targetItem, modArgs);
                bool usePrismatic  = false;
                switch (modType)
                {
                case CustomItemPropertyType.RedMod:
                    if (slots.FilledRedSlots < slots.RedSlots)
                    {
                        targetItem.SetLocalInt("MOD_SLOT_RED_" + (slots.FilledRedSlots + 1), modID);
                        targetItem.SetLocalString("MOD_SLOT_RED_DESC_" + (slots.FilledRedSlots + 1), description);
                        player.SendMessage("Mod installed into " + _color.Red("red") + " slot #" + (slots.FilledRedSlots + 1));
                    }
                    else
                    {
                        usePrismatic = true;
                    }
                    break;

                case CustomItemPropertyType.BlueMod:
                    if (slots.FilledBlueSlots < slots.BlueSlots)
                    {
                        targetItem.SetLocalInt("MOD_SLOT_BLUE_" + (slots.FilledBlueSlots + 1), modID);
                        targetItem.SetLocalString("MOD_SLOT_BLUE_DESC_" + (slots.FilledBlueSlots + 1), description);
                        player.SendMessage("Mod installed into " + _color.Blue("blue") + " slot #" + (slots.FilledBlueSlots + 1));
                    }
                    else
                    {
                        usePrismatic = true;
                    }
                    break;

                case CustomItemPropertyType.GreenMod:
                    if (slots.FilledBlueSlots < slots.GreenSlots)
                    {
                        targetItem.SetLocalInt("MOD_SLOT_GREEN_" + (slots.FilledGreenSlots + 1), modID);
                        targetItem.SetLocalString("MOD_SLOT_GREEN_DESC_" + (slots.FilledGreenSlots + 1), description);
                        player.SendMessage("Mod installed into " + _color.Green("green") + " slot #" + (slots.FilledGreenSlots + 1));
                    }
                    else
                    {
                        usePrismatic = true;
                    }
                    break;

                case CustomItemPropertyType.YellowMod:
                    if (slots.FilledBlueSlots < slots.YellowSlots)
                    {
                        targetItem.SetLocalInt("MOD_SLOT_YELLOW_" + (slots.FilledYellowSlots + 1), modID);
                        targetItem.SetLocalString("MOD_SLOT_YELLOW_DESC_" + (slots.FilledYellowSlots + 1), description);
                        player.SendMessage("Mod installed into " + _color.Yellow("yellow") + " slot #" + (slots.FilledYellowSlots + 1));
                    }
                    else
                    {
                        usePrismatic = true;
                    }
                    break;
                }

                if (usePrismatic)
                {
                    string prismaticText = _mod.PrismaticString();
                    targetItem.SetLocalInt("MOD_SLOT_PRISMATIC_" + (slots.FilledPrismaticSlots + 1), modID);
                    targetItem.SetLocalString("MOD_SLOT_PRISMATIC_DESC_" + (slots.FilledPrismaticSlots + 1), description);
                    player.SendMessage("Mod installed into " + prismaticText + " slot #" + (slots.FilledPrismaticSlots + 1));
                }

                targetItem.RecommendedLevel += levelIncrease;
                modItem.Destroy();

                SkillType skillType;
                if (ItemService.ArmorBaseItemTypes.Contains(targetItem.BaseItemType))
                {
                    skillType = SkillType.Armorsmith;
                }
                else if (ItemService.WeaponBaseItemTypes.Contains(targetItem.BaseItemType))
                {
                    skillType = SkillType.Weaponsmith;
                }
                else
                {
                    return;
                }

                int rank = _skill.GetPCSkillRank(player, skillType);
                int xp   = (int)_skill.CalculateRegisteredSkillLevelAdjustedXP(400, modLevel, rank);
                _skill.GiveSkillXP(player, skillType, xp);
            });
        }
示例#29
0
        public static void CompleteQuest(NWPlayer player, NWObject questOwner, int questID, ItemVO selectedItem)
        {
            if (!player.IsPlayer)
            {
                return;
            }

            Quest         quest   = DataService.Single <Quest>(x => x.ID == questID);
            PCQuestStatus pcState = DataService.Single <PCQuestStatus>(x => x.PlayerID == player.GlobalID && x.QuestID == questID);

            QuestState finalState = DataService.GetAll <QuestState>().Where(x => x.QuestID == questID).OrderBy(o => o.Sequence).Last();

            if (finalState == null)
            {
                player.SendMessage("Could not find final state of quest. Please notify an admin this quest is bugged. (QuestID: " + questID + ")");
                return;
            }

            pcState.CurrentQuestStateID = finalState.ID;
            pcState.CompletionDate      = DateTime.UtcNow;

            if (selectedItem == null)
            {
                var rewardItems = DataService.Where <QuestRewardItem>(x => x.QuestID == questID);
                foreach (QuestRewardItem reward in rewardItems)
                {
                    _.CreateItemOnObject(reward.Resref, player.Object, reward.Quantity);
                }
            }
            else
            {
                _.CreateItemOnObject(selectedItem.Resref, player.Object, selectedItem.Quantity);
            }

            if (quest.RewardGold > 0)
            {
                _.GiveGoldToCreature(player.Object, quest.RewardGold);
            }

            if (quest.RewardKeyItemID != null)
            {
                KeyItemService.GivePlayerKeyItem(player, (int)quest.RewardKeyItemID);
            }

            if (quest.RemoveStartKeyItemAfterCompletion && quest.StartKeyItemID != null)
            {
                KeyItemService.RemovePlayerKeyItem(player, (int)quest.StartKeyItemID);
            }

            if (!string.IsNullOrWhiteSpace(quest.MapNoteTag))
            {
                MapPinService.DeleteMapPin(player, "QST_MAP_NOTE_" + questID);
            }

            if (quest.RewardFame > 0)
            {
                PCRegionalFame     fame   = DataService.SingleOrDefault <PCRegionalFame>(x => x.PlayerID == player.GlobalID && x.FameRegionID == quest.FameRegionID);
                DatabaseActionType action = DatabaseActionType.Update;

                if (fame == null)
                {
                    fame = new PCRegionalFame
                    {
                        PlayerID     = player.GlobalID,
                        FameRegionID = quest.FameRegionID,
                        Amount       = 0
                    };

                    action = DatabaseActionType.Insert;
                }

                fame.Amount += quest.RewardFame;
                DataService.SubmitDataChange(fame, action);
            }

            player.SendMessage("Quest '" + quest.Name + "' complete!");
            DataService.SubmitDataChange(pcState, DatabaseActionType.Update);
            _.RemoveJournalQuestEntry(quest.JournalTag, player, FALSE);

            if (!string.IsNullOrWhiteSpace(quest.OnCompleteRule) && questOwner != null)
            {
                var rule = GetQuestRule(quest.OnCompleteRule);

                string[] args = null;
                if (!string.IsNullOrWhiteSpace(quest.OnCompleteArgs))
                {
                    args = quest.OnCompleteArgs.Split(',');
                }
                rule.Run(player, questOwner, questID, args);
            }

            MessageHub.Instance.Publish(new QuestCompletedMessage(player, questID));
        }
示例#30
0
        private void HealTarget(NWPlayer oPC, NWObject oTarget, int lightBonus, int level)
        {
            var   effectiveStats = _playerStat.GetPlayerItemEffectiveStats(oPC);
            int   amount;
            float length;
            int   regenAmount;
            int   min = 1;

            int wisdom       = oPC.WisdomModifier;
            int intelligence = oPC.IntelligenceModifier;

            min += lightBonus / 3 + wisdom / 2 + intelligence / 3;

            switch (level)
            {
            case 1:
                amount      = _random.D6(2, min);
                length      = 0.0f;
                regenAmount = 0;
                break;

            case 2:
                amount      = _random.D6(2, min);
                length      = 6.0f;
                regenAmount = 1;
                break;

            case 3:
                amount      = _random.D12(2, min);
                length      = 6.0f;
                regenAmount = 1;
                break;

            case 4:
                amount      = _random.D12(2, min);
                length      = 12.0f;
                regenAmount = 1;
                break;

            case 5:
                amount      = _random.D12(2, min);
                length      = 6.0f;
                regenAmount = 2;
                break;

            case 6:
                amount      = _random.D12(2, min);
                length      = 12.0f;
                regenAmount = 2;
                break;

            case 7:
                amount      = _random.D12(3, min);
                length      = 12.0f;
                regenAmount = 2;
                break;

            case 8:
                amount      = _random.D12(3, min);
                length      = 6.0f;
                regenAmount = 4;
                break;

            case 9:
                amount      = _random.D12(4, min);
                length      = 6.0f;
                regenAmount = 4;
                break;

            case 10:
                amount      = _random.D12(4, min);
                length      = 12.0f;
                regenAmount = 4;
                break;

            case 11:     // Only attainable with background bonus
                amount      = _random.D12(5, min);
                length      = 12.0f;
                regenAmount = 4;
                break;

            default: return;
            }

            int luck = _perk.GetPCPerkLevel(oPC, PerkType.Lucky) + effectiveStats.Luck;

            if (_random.Random(100) + 1 <= luck)
            {
                length = length * 2;
                oPC.SendMessage("Lucky heal!");
            }

            Effect heal = _.EffectHeal(amount);

            _.ApplyEffectToObject(DURATION_TYPE_INSTANT, heal, oTarget.Object);

            if (length > 0.0f && regenAmount > 0)
            {
                Effect regen = _.EffectRegenerate(regenAmount, 1.0f);
                _.ApplyEffectToObject(DURATION_TYPE_TEMPORARY, regen, oTarget.Object, length + 0.1f);
            }

            Effect vfx = _.EffectVisualEffect(VFX_IMP_HEALING_M);

            _.ApplyEffectToObject(DURATION_TYPE_INSTANT, vfx, oTarget.Object);
        }