Files

433 lines
18 KiB
C#

using System;
using System.Drawing;
using Library;
using Library.Network;
using Library.SystemModels;
using Server.DBModels;
using Server.Envir;
using S = Library.Network.ServerPackets;
namespace Zircon.Server.Models
{
public class NPCObject : MapObject
{
public override ObjectType Race {get{return ObjectType.NPC;}}
public NPCInfo NPCInfo;
public override string Name {get{return NPCInfo.NPCName;}}
public override bool Blocking { get { return Visible; } }
public void NPCCall(PlayerObject ob, NPCPage page)
{
while (true)
{
if (page == null) return;
NPCPage failPage;
if (!CheckPage(ob, page, out failPage))
{
page = failPage;
continue;
}
DoActions(ob, page);
if (page.SuccessPage != null)
{
page = page.SuccessPage;
continue;
}
if (string.IsNullOrEmpty(page.Say))
{
ob.NPC = null;
ob.NPCPage = null;
ob.Enqueue(new S.NPCClose());
return;
}
ob.NPC = this;
ob.NPCPage = page;
ob.Enqueue(new S.NPCResponse { ObjectID = ObjectID, Index = page.Index });
break;
}
}
private void DoActions(PlayerObject ob, NPCPage page)
{
foreach (NPCAction action in page.Actions)
{
switch (action.ActionType)
{
case NPCActionType.Teleport:
if (action.MapParameter1 == null) return;
Map map = SEnvir.GetMap(action.MapParameter1);
if (action.IntParameter1 == 0 && action.IntParameter2 == 0)
ob.Teleport(map, map.GetRandomLocation());
else
ob.Teleport(map, new Point(action.IntParameter1, action.IntParameter2));
break;
case NPCActionType.TakeGold:
ob.Gold -= action.IntParameter1;
ob.GoldChanged();
break;
case NPCActionType.ChangeElement:
UserItem weapon = ob.Equipment[(int) EquipmentSlot.Weapon];
S.ItemStatsChanged result = new S.ItemStatsChanged { GridType = GridType.Equipment, Slot = (int)EquipmentSlot.Weapon, NewStats = new Stats() };
result.NewStats[Stat.WeaponElement] = action.IntParameter1 - weapon.Stats[Stat.WeaponElement];
weapon.AddStat(Stat.WeaponElement, action.IntParameter1 - weapon.Stats[Stat.WeaponElement], StatSource.Refine);
weapon.StatsChanged();
ob.RefreshStats();
ob.Enqueue(result);
break;
case NPCActionType.ChangeHorse:
ob.Character.Account.Horse = (HorseType) action.IntParameter1;
ob.RemoveMount();
ob.RefreshStats();
if (ob.Character.Account.Horse != HorseType.None) ob.Mount();
break;
case NPCActionType.GiveGold:
long gold = ob.Gold + action.IntParameter1;
ob.Gold = (long) gold;
ob.GoldChanged();
break;
case NPCActionType.Marriage:
ob.MarriageRequest();
break;
case NPCActionType.Divorce:
ob.MarriageLeave();
break;
case NPCActionType.RemoveWeddingRing:
ob.MarriageRemoveRing();
break;
case NPCActionType.GiveItem:
if (action.ItemParameter1 == null) continue;
ItemCheck check = new ItemCheck(action.ItemParameter1, action.IntParameter1, UserItemFlags.None, TimeSpan.Zero);
if (!ob.CanGainItems(false, check)) continue;
while (check.Count > 0)
ob.GainItem(SEnvir.CreateFreshItem(check));
break;
case NPCActionType.TakeItem:
if (action.ItemParameter1 == null) continue;
ob.TakeItem(action.ItemParameter1, action.IntParameter1);
break;
case NPCActionType.ResetWeapon:
ob.NPCResetWeapon();
break;
case NPCActionType.GiveItemExperience:
if (action.ItemParameter1 == null) continue;
check = new ItemCheck(action.ItemParameter1, action.IntParameter1, UserItemFlags.None, TimeSpan.Zero);
if (!ob.CanGainItems(false, check)) continue;
while (check.Count > 0)
{
UserItem item = SEnvir.CreateFreshItem(check);
item.Experience = action.IntParameter2;
if (item.Experience >= Globals.AccessoryExperienceList[item.Level])
{
item.Experience -= Globals.AccessoryExperienceList[item.Level];
item.Level++;
item.Flags |= UserItemFlags.Refinable;
}
ob.GainItem(item);
}
break;
case NPCActionType.SpecialRefine:
ob.NPCSpecialRefine(action.StatParameter1, action.IntParameter1);
break;
case NPCActionType.Rebirth:
if (ob.Character.Rebirth >= Config.最高转生次数)
{
ob.Connection.ReceiveChat("你的转生次数已达上限,再重生恐怕就醒不过来了.", MessageType.System);
continue;
}
if (ob.Level < Config.转生基础等级 + ob.Character.Rebirth)
{
ob.Connection.ReceiveChat($"下次转生需要 {Config.转生基础等级 + ob.Character.Rebirth} 级,你目前实力还不够.", MessageType.System);
continue;
}
ob.NPCRebirth();
break;
}
}
}
private bool CheckPage(PlayerObject ob, NPCPage page, out NPCPage failPage)
{
failPage = null;
foreach (NPCCheck check in page.Checks)
{
failPage = check.FailPage;
UserItem weap;
switch (check.CheckType)
{
case NPCCheckType.Level:
if (!Compare(check.Operator, ob.Level, check.IntParameter1)) return false;
break;
case NPCCheckType.Class:
if (!Compare(check.Operator, (int)ob.Class, check.IntParameter1)) return false;
break;
case NPCCheckType.Gold:
if (!Compare(check.Operator, ob.Gold, check.IntParameter1)) return false;
break;
case NPCCheckType.HasWeapon:
if (ob.Equipment[(int)EquipmentSlot.Weapon] != null != (check.Operator == Operator.Equal)) return false;
break;
case NPCCheckType.WeaponLevel:
if (!Compare(check.Operator, ob.Equipment[(int)EquipmentSlot.Weapon].Level, check.IntParameter1)) return false;
break;
case NPCCheckType.WeaponLevelFull:
bool full = SEnvir.GetWeaponLimitLevel(ob.Equipment[(int)EquipmentSlot.Weapon].Info.Rarity) <= ob.Equipment[(int)EquipmentSlot.Weapon].Level;
if (!Compare(check.Operator, full ? 1 : 0, check.IntParameter1)) return false;
break;
case NPCCheckType.WeaponCanRefine:
if ((ob.Equipment[(int)EquipmentSlot.Weapon].Flags & UserItemFlags.Refinable) == UserItemFlags.Refinable != (check.Operator == Operator.Equal)) return false;
break;
case NPCCheckType.WeaponAddedStats:
if (!Compare(check.Operator, ob.Equipment[(int)EquipmentSlot.Weapon].Stats[check.StatParameter1], check.IntParameter1)) return false;
break;
case NPCCheckType.WeaponElement:
weap = ob.Equipment[(int)EquipmentSlot.Weapon];
Stat element;
int value = 0;
switch ((Element)check.IntParameter1)
{
case Element.None:
value += weap.Stats.GetWeaponElementValue();
value += weap.Info.Stats.GetWeaponElementValue();
break;
case Element.Fire:
element = weap.Stats.GetWeaponElement();
if (element == Stat.None)
element = weap.Info.Stats.GetWeaponElement();
if (element == Stat.FireAttack)
{
value += weap.Stats.GetWeaponElementValue();
value += weap.Info.Stats.GetWeaponElementValue();
}
break;
case Element.Ice:
element = weap.Stats.GetWeaponElement();
if (element == Stat.None)
element = weap.Info.Stats.GetWeaponElement();
if (element == Stat.IceAttack)
{
value += weap.Stats.GetWeaponElementValue();
value += weap.Info.Stats.GetWeaponElementValue();
}
break;
case Element.Lightning:
element = weap.Stats.GetWeaponElement();
if (element == Stat.None)
element = weap.Info.Stats.GetWeaponElement();
if (element == Stat.LightningAttack)
{
value += weap.Stats.GetWeaponElementValue();
value += weap.Info.Stats.GetWeaponElementValue();
}
break;
case Element.Wind:
element = weap.Stats.GetWeaponElement();
if (element == Stat.None)
element = weap.Info.Stats.GetWeaponElement();
if (element == Stat.WindAttack)
{
value += weap.Stats.GetWeaponElementValue();
value += weap.Info.Stats.GetWeaponElementValue();
}
break;
case Element.Holy:
element = weap.Stats.GetWeaponElement();
if (element == Stat.None)
element = weap.Info.Stats.GetWeaponElement();
if (element == Stat.HolyAttack)
{
value += weap.Stats.GetWeaponElementValue();
value += weap.Info.Stats.GetWeaponElementValue();
}
break;
case Element.Dark:
element = weap.Stats.GetWeaponElement();
if (element == Stat.None)
element = weap.Info.Stats.GetWeaponElement();
if (element == Stat.DarkAttack)
{
value += weap.Stats.GetWeaponElementValue();
value += weap.Info.Stats.GetWeaponElementValue();
}
break;
case Element.Phantom:
element = weap.Stats.GetWeaponElement();
if (element == Stat.None)
element = weap.Info.Stats.GetWeaponElement();
if (element == Stat.PhantomAttack)
{
value += weap.Stats.GetWeaponElementValue();
value += weap.Info.Stats.GetWeaponElementValue();
}
break;
}
if (!Compare(check.Operator, value, check.IntParameter2)) return false;
break;
case NPCCheckType.PKPoints:
if (!Compare(check.Operator, ob.Stats[Stat.PKPoint], check.IntParameter1 == 0 ? Config.RedPoint : check.IntParameter1) && ob.Stats[Stat.Redemption] == 0)
return false;
break;
case NPCCheckType.Horse:
if (!Compare(check.Operator, (int)ob.Character.Account.Horse, check.IntParameter1)) return false;
break;
case NPCCheckType.Marriage:
if (check.Operator == Operator.Equal)
{
if (ob.Character.Partner == null) return false;
}
else
{
if (ob.Character.Partner != null) return false;
}
break;
case NPCCheckType.WeddingRing:
if (check.Operator == Operator.Equal)
{
if (ob.Equipment[(int) EquipmentSlot.RingL] == null || (ob.Equipment[(int) EquipmentSlot.RingL].Flags & UserItemFlags.Marriage) != UserItemFlags.Marriage) return false;
}
else
{
if (ob.Equipment[(int)EquipmentSlot.RingL] != null && (ob.Equipment[(int)EquipmentSlot.RingL].Flags & UserItemFlags.Marriage) == UserItemFlags.Marriage) return false;
}
break;
case NPCCheckType.HasItem:
if (check.ItemParameter1 == null) continue;
if (!Compare(check.Operator, ob.GetItemCount(check.ItemParameter1), check.IntParameter1)) return false;
break;
case NPCCheckType.CanGainItem:
if (check.ItemParameter1 == null) continue;
ItemCheck itemCheck = new ItemCheck(check.ItemParameter1, check.IntParameter1, UserItemFlags.None, TimeSpan.Zero);
if (!ob.CanGainItems(false, itemCheck)) return false;
break;
case NPCCheckType.CanResetWeapon:
if (check.Operator == Operator.Equal)
{
if (SEnvir.Now < ob.Equipment[(int)EquipmentSlot.Weapon].ResetCoolDown) return false;
}
else
{
if (SEnvir.Now >= ob.Equipment[(int)EquipmentSlot.Weapon].ResetCoolDown) return false;
}
break;
case NPCCheckType.Random:
if (!Compare(check.Operator, SEnvir.Random.Next(check.IntParameter1), check.IntParameter2)) return false;
break;
}
}
return true;
}
private bool Compare(Operator op, long pValue, long cValue)
{
switch (op)
{
case Operator.Equal:
return pValue == cValue;
case Operator.NotEqual:
return pValue != cValue;
case Operator.LessThan:
return pValue < cValue;
case Operator.LessThanOrEqual:
return pValue <= cValue;
case Operator.GreaterThan:
return pValue > cValue;
case Operator.GreaterThanOrEqual:
return pValue >= cValue;
default: return false;
}
}
public override Packet GetInfoPacket(PlayerObject ob)
{
return new S.ObjectNPC
{
ObjectID = ObjectID,
NPCIndex = NPCInfo.Index,
CurrentLocation = CurrentLocation,
Direction = Direction,
};
}
public override bool CanBeSeenBy(PlayerObject ob)
{
return Visible && base.CanBeSeenBy(ob);
}
public override bool CanDataBeSeenBy(PlayerObject ob)
{
return false;
}
public override Packet GetDataPacket(PlayerObject ob)
{
return null;
}
}
}