您的位置:首页 > 运维架构

Top-down-Rpg-Start-kit插件的使用与二次开发

2015-04-19 16:27 501 查看
这几天都在说仙剑Demo,为啥突然讲Top-down-Rpg-Start-kit,因为Top-down-Rpg-Start-kit是个非常完整的动作游戏插件,根据其完整文档可以快速开发单机的rpg游戏,我们做的Demo是回合制的,但这个插件的交易系统,状态机,背包系统,小地图系统做的非常好,我们的demo后面的几个系统都使用了Top-down-Rpg-Start-kit的插件源码,利用别人的成熟代码,来完善自己的游戏快速开发,这是我多年的一个开发习惯,废话不说,我们开始,不过开篇可能有些奇怪,因为这个文档我是去年12月份写的,当时是在学习Top-down-Rpg-Start-kit的插件并且整合游戏的任务系统,但后来发现Top-down-Rpg-Start-kit1.2自己加入了任务系统,并且我的实验项目也基本完成所以停了下来,后来开发仙剑的Demo,所以这个文档上面的源码与Top-down-Rpg-Start-kit1.0的源码有很多地方不太一样,不过具体修改的源码我会帖出来,并且写详细的中文注释。我们开始

这一篇的篇幅都是在讲我整喝一个任务系统到这个插件的全过程,因为直接看估计很难看得懂,所以后面我会提供完整的整合任务系统的工程文件,所以到时候再看把,建议大家跳过这一篇,直接看下一篇,等到我提供的工程文件放出来,大家在回来看,否则估计会有很多小伙伴骂我。

这个任务系统需要的源码包下载地址密码wjd3,这个包复制进下载的Top-down-Rpg-Start-kit1.0,然后按照最后Hierarchy设置,完整的工程文件因为太大,所以以后有时间放上来。



先上一张插件的logo,新建

建立新文件夹,存放修改后的模型元件,代码,资源

建立人物模型组件

1.添加模型(模型要包括动作)到Hierarchy窗口



2.添加角色控制脚本到模型上


3.把人物模型层layer和标签tag改为player

任务系统开发

playerBase.cs修改

if(globalPrefabs== null){
//globalPrefabs=GameObject.FindGameObjectWithTag("GameMaster").GetComponent<GlobalPrefabs>();
}
OptionsMenuGUI.cs
//gameSettings=GameObject.FindGameObjectWithTag("GameMaster").GetComponent<GameSettings>();
MyGUI.cs
//DisplayPlayerVitalsAndExp();
制作一个用于测试的敌人修改

中的预制件






注意上面的PlayerNew.cs是我们后加的,源码

using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using System.Collections;
//You must include these namespaces
//to use BinaryFormatter
using System;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;

public class PlayerNew : PlayerBase {

#region "Inventorys, Banks, Stashes"
public int MaxInventorySpace = 25;
private List<Item> _inventory = new List<Item>();
public List<Item> Inventory {
get{return _inventory;}
set{_inventory = value;}
}

private int MaxStashSpace = 125;
private List<Item> _stash = new List<Item>();
public List<Item> Stash {
get{return _stash;}
set{_stash = value;}
}

#endregion

#region "Tracking"

private List<NPCQuest> _QuestsComplete = new List<NPCQuest>();
public List<NPCQuest> questsComplete {
get{return _QuestsComplete;}
set{_QuestsComplete = value;}
}

private List<NPCQuest> _questsInProgress = new List<NPCQuest>();
public List<NPCQuest> QuestsInProgress {
get{return _questsInProgress;}
set{_questsInProgress = value;}
}
#endregion

#region "Achievement Variables"
private int monstersKilled = 0;
public int MonstersKilled {
get{return monstersKilled;}
set{monstersKilled = value;}
}

private List<string> _bossesKilled = new List<string>();
public List<string> BossesKilled {
get{return _bossesKilled;}
set{_bossesKilled = value;}
}

#endregion

#region "Variables"

private bool canConsume = true;

#endregion
// Use this for initialization
void Start ()
{
//For testing /////////////////////////////////////
ModifyAttribute(AttributeName.Strength,10);
ModifyAttribute(AttributeName.Dexterity,10);
ModifyAttribute(AttributeName.Vitality,10);
ModifyAttribute(AttributeName.Intelligence,10);
Name = "Player";
RefreshVitals();
///////////////////////////////////////////////////

Item item = ItemGenerator.CreateItem ("consum","random",100);
item.CurStacks = 10;
Item itemcopy = DeepCopy.CopyItem (item);
Inventory.Add (item);
Inventory.Add (itemcopy);
}

public void OnEnable(){
Messenger<string>.AddListener("MonsterKilled",AddMobsKilled);
}

public void OnDisable(){
Messenger<string>.RemoveListener("MonsterKilled",AddMobsKilled);
}

// Update is called once per frame
void Update ()
{
if(Input.GetKeyDown(KeyCode.P)){
for (int i = 0; i < Vitals.Length; i++) {
_vitals[i].CurValue = (int)(0.5f * _vitals[i].CurValue);
}
}

if(Input.GetKeyDown(KeyCode.O)){
GiveStuff();
}

}

//Methods

public void ModifyAttribute(AttributeName att, int amount)
{
GetAttribute((int)att).BaseValue += amount;
UpdateStats();
}

public bool ModifyGold(int amount){
Gold += amount;
return true;
}

//Mobs killed
private void AddMobsKilled(string mobName){
MonstersKilled += 1;
if(mobName.StartsWith("BOSS")){
BossesKilled.Add (mobName.Substring(4));
}
}

//Bank Adding
public bool AddToBank(int arrayNum){

if(_inventory[arrayNum].MaxStacks > 1){	//maybe check this first
Debug.Log ("Bank is not full!,AddToBank"+_inventory[arrayNum].MaxStacks);
bool addedToStack = CheckBankStack(_inventory[arrayNum]);
if(addedToStack){
_inventory.RemoveAt (arrayNum);
Debug.Log ("Bank is not full!,AddToBank,arrayNum"+arrayNum);
Debug.Log ("Bank is not full!,AddToBank,"+_inventory);
return true;
}
}

if(Stash.Count < MaxStashSpace){
Stash.Add (_inventory[arrayNum]);
_inventory.RemoveAt (arrayNum);
return true;
}
Debug.Log ("Bank is full!");
return false;
}

private bool CheckBankStack(Item item){

bool itemsAdded = false;
foreach(Item i in Stash){
//Is the item already there
if(i.Name == item.Name){
Debug.Log("CheckBankStack==="+i.ItemType);
if(i.ItemType == ItemEquipType.QuestItem){
Debug.Log ("Cannot bank quest items");
return false;
}
//Is there space in that stack to add the current item
if(i.CurStacks + item.CurStacks <= i.MaxStacks){
i.CurStacks += item.CurStacks;
itemsAdded = true;
return true;
}
}
}

if(!itemsAdded){
//Manually Check Inventory
if(Stash.Count < MaxStashSpace){
Stash.Add (item);
return true;
}
else {
Debug.Log("Bank too full to add more of this stack");
}
}

return false;

}

//Inventory Adding
public bool AddItem(Item item){
if(item.Name.Contains("Gold")){
bool isNotGold = true;

//Just in case we want to put goldin item name, we check if name has numbers in it
foreach (char c in item.Name)
if (char.IsNumber(c))
isNotGold = false;

if(!isNotGold)
ModifyGold(item.Value);
return true;
}

if(item.MaxStacks > 1){	//maybe check this first
bool addedToStack = CheckStack(item);
if(addedToStack)
return true;
}

if(Inventory.Count < MaxInventorySpace){
Inventory.Add (item);
return true;
}

return false;
}

private bool CheckStack(Item item){
bool itemsAdded = false;
foreach(Item i in Inventory){
//Is the item already there
if(i.Name == item.Name){
if(i.ItemType == ItemEquipType.QuestItem){
i.CurStacks += item.CurStacks;
if(i.CurStacks > i.MaxStacks)
i.CurStacks = i.MaxStacks;

return true;
}
//Is there space in that stack to add the current item
if(i.CurStacks + item.CurStacks <= i.MaxStacks){
i.CurStacks += item.CurStacks;
itemsAdded = true;
return true;
}
}
}

if(!itemsAdded){
//Manually Check Inventory
if(Inventory.Count < MaxInventorySpace){
Inventory.Add (item);
return true;
}
else {
Debug.Log("Inventory too full to add more of this stack");
}
}

return false;

}

//Stat Handling
public void ResetStats()
{
HealthFromAttr = ManaFromAttr = EnergyFromAttr = 0;
PlayerArmor = PlayerDamageBlocked = StrEquipValue = DexEquipValue = IntEquipValue = VitEquipValue = 0;
PlayerChanceToBlock = PlayerMoveSpeedBuff = 0.0f;

CritChance = BaseCritChance;
AttackSpeed = MaxDamage = 1;
DmgVariance = 0.1f;
CritDamage = 2;
}

public List<Item> AllEquippedItems(){
return new List<Item>(){
EquipedArmorBack, EquipedArmorChest, EquipedArmorFeet, EquipedArmorGloves, EquipedArmorHead,
EquipedArmorLegs, EquipedWeapon
};
}

public void UpdateStats()
{
ResetStats();

List<Item> EquippedItems = AllEquippedItems();

foreach(Item item in EquippedItems){
if(item != null){
BuffItem equippedItem = item as BuffItem;

if(equippedItem.EquippedSockets.Count > 0){
foreach(AttributeBuff ab in equippedItem.EquippedSockets[0].AttribBuffs){
if (ab.attribute == AttributeName.Vitality){
VitEquipValue += ab.amount;
}
else if(ab.attribute == AttributeName.Strength){
StrEquipValue += ab.amount;
}
else if(ab.attribute == AttributeName.Dexterity){
DexEquipValue += ab.amount;
}
else if(ab.attribute == AttributeName.Intelligence){
IntEquipValue += ab.amount;
}
}

foreach(VitalBuff vb in equippedItem.EquippedSockets[0].VitalBuffs){
if (vb.vital == VitalName.Health){
HealthFromAttr += vb.amount;

}
else if(vb.vital == VitalName.Mana){
ManaFromAttr += vb.amount;
}
else if(vb.vital == VitalName.Energy){
EnergyFromAttr += vb.amount;
}
}
}

if (item.ItemType == ItemEquipType.Clothing){
Armor equippedArmor = item as Armor;
PlayerArmor += equippedArmor.ArmorAmt;
PlayerChanceToBlock += equippedArmor.ChanceToBlock;
PlayerDamageBlocked += equippedArmor.DamageBlocked;
PlayerMoveSpeedBuff += equippedArmor.MoveSpeedBuff;
}

if(equippedItem.ItemType == ItemEquipType.Weapon){
Weapon equippedWep= equippedItem as Weapon;

MaxDamage += equippedWep.MaxDamage;
DmgVariance = equippedWep.DmgVariance; //replace
AttackSpeed = equippedWep.AttackSpeed; //replace
CritDamage += equippedWep.CritDamage; //additive, always 2.0
}

foreach(AttributeBuff ab in equippedItem.AttribBuffs){
if (ab.attribute == AttributeName.Vitality){
VitEquipValue += ab.amount;
}
else if(ab.attribute == AttributeName.Strength){
StrEquipValue += ab.amount;
}
else if(ab.attribute == AttributeName.Dexterity){
DexEquipValue += ab.amount;
}
else if(ab.attribute == AttributeName.Intelligence){
IntEquipValue += ab.amount;
}
}

foreach(VitalBuff vb in equippedItem.VitalBuffs){
if (vb.vital == VitalName.Health){
HealthFromAttr += vb.amount;

}
else if(vb.vital == VitalName.Mana){
ManaFromAttr += vb.amount;
}
else if(vb.vital == VitalName.Energy){
EnergyFromAttr += vb.amount;
}
}
}

}

foreach(Attribute att in _attributes){
if(att.Name == "Strength")
{
att.EquipValue = StrEquipValue;
}
else if(att.Name == "Vitality")
{
att.EquipValue = VitEquipValue;
}
else if(att.Name == "Dexterity")
{
att.EquipValue = DexEquipValue;
}
else if(att.Name == "Intelligence")
{
att.EquipValue = IntEquipValue;
}
att.RecalculateValue();
}

ScaleStats();
}

private void ScaleStats(){
//Scale Vitals based on Attributes
foreach(Vital vit in _vitals){
if(vit.Name == "Health")
{
HealthFromAttr += GetAttribute((int)AttributeName.Strength).AttributeValue * 10 +
GetAttribute((int)AttributeName.Vitality).AttributeValue * 50;

vit.MaxValue = HealthFromAttr ;
}
else if(vit.Name == "Mana")
{
ManaFromAttr += GetAttribute((int)AttributeName.Intelligence).AttributeValue * 10;
vit.MaxValue = ManaFromAttr ;
}
else if(vit.Name == "Energy")
{
EnergyFromAttr += GetAttribute((int)AttributeName.Dexterity).AttributeValue * 10;
vit.MaxValue = EnergyFromAttr ;
}
}

//Scale damage based off stat
MaxDamage += GetAttribute((int)AttributeName.Strength).AttributeValue * 2;

//Scale armour based off stat
PlayerArmor += GetAttribute((int)AttributeName.Vitality).AttributeValue * 2;

//Scale Crit chance based on level
BaseCritChance = Level * 0.002f;

//Recalc Movement Speed
MoveSpeed = 1.0f + PlayerMoveSpeedBuff;

//Recalc Crit Chance
float wepCritChance = EquipedWeapon != null ? (EquipedWeapon as Weapon).CritChance : 0;
CritChance = BaseCritChance + wepCritChance;
}

private void RefreshVitals(){
foreach(Vital v in Vitals){
v.CurValue = v.MaxValue;
}
}

public void Respawn(){
//Load level if needed
GameObject RespawnLocation = GameObject.FindGameObjectWithTag("Respawn");
if(RespawnLocation != null) {
gameObject.transform.position = RespawnLocation.transform.position;
}
else {
Debug.Log ("No respawn gameObject found to use as respawn location.");
}

CharacterControl.useNewPosition = true;
CharacterControl.newPosition = transform.position;
GetVital((int)VitalName.Health).CurValue = (int)((GetVital((int)VitalName.Health).MaxValue)*.75);	//respawn with 10% health
GetVital((int)VitalName.Mana).CurValue = (int)((GetVital((int)VitalName.Mana).MaxValue)*.75f);
GetVital((int)VitalName.Energy).CurValue = (int)((GetVital((int)VitalName.Energy).MaxValue)*.75f);
Alive = true;
}

public bool UseConsumable(int getVitalInt, int amount){
if(canConsume){
StartCoroutine(UsePot(getVitalInt, amount));
return true;
}

return false;
}

IEnumerator UsePot(int getVitalInt, int amount){
canConsume = false;
GetVital(getVitalInt).CurValue += amount;
yield return new WaitForSeconds(1.0f);
canConsume = true;
}

//Exit Combat Vars
public int secondsBeforeExitingCombat = 5;
public int secondsWaited = 0;

public void CheckForExitCombat(){
if(!_waitingToExitCombat)
InvokeRepeating("TryToExitCombat",1.0f,1.0f);
else{
CancelInvoke("TryToExitCombat");
secondsWaited = 0;
InvokeRepeating("TryToExitCombat",1.0f,1.0f);
}
}

public void TryToExitCombat(){
WaitingToExitCombat = true;
secondsWaited += 1;
if(secondsWaited > secondsBeforeExitingCombat){
secondsWaited = 0;
CancelInvoke("TryToExitCombat");
playerState = PlayerState.Normal;
WaitingToExitCombat = false;
}
}

void GiveStuff(){
AddItem(ItemGenerator.CreateItem("weapon","legendary",2));

Item fireItem = ItemGenerator.CreateItem("weapon","legendary",2);
Weapon fireWeapon = fireItem as Weapon;
fireWeapon.DmgType = DamageType.Fire;
fireWeapon.DmgValue = 100;
fireWeapon.CritChance = 0.7f;
fireWeapon.CritDamage = 4.0f;
AddItem(fireWeapon);

Item waterItem = ItemGenerator.CreateItem("weapon","legendary",2);
Weapon waterWeapon = waterItem as Weapon;
waterWeapon.DmgType = DamageType.Water;
waterWeapon.DmgValue = 100;
AddItem(waterWeapon);

Item knockBackItem = ItemGenerator.CreateItem("weapon","legendary",2);
Weapon knockBackWep = knockBackItem as Weapon;
knockBackWep.Proc = ProcType.Knockback;
knockBackWep.ProcModifier = 0.8f;
AddItem(knockBackWep);

Item stunItem = ItemGenerator.CreateItem("weapon","legendary",2);
Weapon stunWep = stunItem as Weapon;
stunWep.Proc = ProcType.Stun;
stunWep.ProcModifier = 0.8f;
AddItem(stunWep);

Item slowItem = ItemGenerator.CreateItem("weapon","legendary",2);
Weapon slowWep = slowItem as Weapon;
slowWep.Proc = ProcType.Slow;
slowWep.ProcModifier = 0.8f;
AddItem(slowWep);

Item poisonItem = ItemGenerator.CreateItem("weapon","legendary",2);
Weapon poisonWep = poisonItem as Weapon;
poisonWep.Proc = ProcType.Poison;
poisonWep.ProcModifier = 0.8f;
AddItem(poisonWep);

AddItem(ItemGenerator.CreateItem("armor","legendary",2));
AddItem(ItemGenerator.CreateItem("armor","legendary",2));
AddItem(ItemGenerator.CreateItem("armor","legendary",2));

AddItem(ItemGenerator.CreateItem("consum","legendary",25));
AddItem(ItemGenerator.CreateItem("consum","legendary",25));
AddItem(ItemGenerator.CreateItem("consum","legendary",25));
AddItem(ItemGenerator.CreateItem("consum","legendary",25));
AddItem(ItemGenerator.CreateItem("consum","legendary",25));
AddItem(ItemGenerator.CreateItem("consum","legendary",25));
AddItem(ItemGenerator.CreateItem("consum","legendary",25));
AddItem(ItemGenerator.CreateItem("consum","legendary",25));
AddItem(ItemGenerator.CreateItem("consum","legendary",25));
AddItem(ItemGenerator.CreateItem("consum","legendary",25));
AddItem(ItemGenerator.CreateItem("consum","legendary",25));

AddItem(ItemGenerator.CreateItem("socket","legendary",10));
AddItem(ItemGenerator.CreateItem("socket","legendary",10));
AddItem(ItemGenerator.CreateItem("socket","legendary",10));
AddItem(ItemGenerator.CreateItem("socket","legendary",10));

ModifyGold(1000);
}
}
代码量比较大,palyernew中用到的几个类

//Add _description for displaying info about an item:
//e.g. "This will heal your health"
//e.g. A might sword forged in gallifrey etc
//e.g. "Quest Item: Hand to Alabar"

using UnityEngine;
//[System.Serializable]
[System.Serializable]
public class Item {
private string _name;
private int _value;				//Gold Value
private RarityTypes _rarity;
private bool _canBeSold;

[System.NonSerialized]
private Texture2D _icon;
private string _iconPath;

private int _curStacks;
private int _maxStacks;

private int _requiredLevel;

private ItemEquipType _itemType;
private bool _canBeDropped;
//Number you can have in one slot, e.g. 1 for equips, 20 for pots

private string _description;

public Item(){
_name = "Unnamed Item";
_value = 100;
_rarity = RarityTypes.Common;
_itemType = ItemEquipType.Clothing;
_requiredLevel = 0;
_canBeSold = true;
_icon = Resources.Load ("Item Icons/defaultItem") as Texture2D;
_iconPath = "Item Icons/defaultItem";
_maxStacks = 1;
_curStacks = 1;
_description = "";
_canBeDropped = true;

}

public Item(string name, int val, RarityTypes rare, ItemEquipType itemType,
int reqLvl, int enchants, bool sellable, int maxStacks,
int curStacks, string description, bool canBeDropped) {

_name = name;
_value = val;
_rarity = rare;
_requiredLevel = reqLvl;
_canBeSold = sellable;
_itemType = itemType;
_maxStacks = maxStacks;
_curStacks = curStacks;
_description = description;
_canBeDropped = canBeDropped;
}

//For Gold only
public Item(string name, int val) {

_name = name;
_value = val;
_icon = Resources.Load("Item Icons/goldItem") as Texture2D;
_iconPath = "Item Icons/goldItem";
}

public string Name{
get{return _name;}
set{_name = value;}
}

public int Value{
get{return _value;}
set{_value = value;}
}

public bool CanBeSold {
get{return _canBeSold;}
set{_canBeSold = value;}
}

public bool CanBeDropped {
get{return _canBeDropped;}
set{_canBeDropped = value;}
}

public RarityTypes Rarity {
get{return _rarity;}
set{_rarity = value;}
}

public ItemEquipType ItemType {
get{return _itemType;}
set{_itemType = value;}
}

public int RequiredLevel {
get{return _requiredLevel;}
set{_requiredLevel = value;}
}

public Texture2D Icon {
get{return _icon;}
set{_icon = value;}
}

public string IconPath {
get{return _iconPath;}
set{_iconPath = value;}
}

public int MaxStacks {
get{return _maxStacks;}
set{_maxStacks = value;}
}

public int CurStacks {
get{return _curStacks;}
set{_curStacks = value;}
}

public string Description {
get{return _description;}
set{_description = value;}
}

public virtual string UniqueIdentifier(){
return (Name+Value.ToString()+RequiredLevel+Description);
}

public virtual string ToolTip() {
if(!Name.Contains("Gold")){
return "Name" + "\n" +
"Value: " + Value;
}

return Value + " Gold!";
}
}

public enum RarityTypes {
Common,
Uncommon,
Rare,
Epic,
Legendary,
Unique,
CraftedItem,

//not rarity, just used for identifying unique items
QuestItem,
CraftItem,
SocketItem
}

public enum ItemEquipType {
Clothing,
Weapon,
Consumable,
QuestItem,
CraftItem,
Socket
}


using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class NPCQuest : MonoBehaviour {
private PlayerNew player;

public int QuestID;
public string QuestName;
public string QuestText;
public string QuestNPCName;
public int QuestExpReward;
public int QuestGoldReward;
public List<Item> QuestReward = new List<Item>();
public bool isComplete;
public bool isAccepted;
public bool isFinished;
public int RewardNum;
public string rewardType;
public RequirementsStatus requirementStatus;

//Quest Requirements
public int[] QuestIDReq;
public int QuestLevelReq;

//Quest Completion Steps
public bool trackSteps;

public string nameOfMob;
public int numberToKill;
public int numberKilled;
public bool killDone;

public string nameOfItem;
public string nameOfMobThatDropsItem;
public int numberToObtain;
public int numberObtained;
public bool itemDone;

public EnableGameObject qego;
public bool EnableQuestGOPerm;
public bool talkingCompletesQuest;
public string nameOfNPCtoTalkTo;
public string[] npcResponse;
public bool talkDone;

//TEMP
public string questTracker;

// Use this for initialization
void Start () {

if(player == null){
player = GameObject.FindGameObjectWithTag("Player").GetComponent<PlayerNew>();
}

trackSteps = true;

for (int i = 0; i < RewardNum; i++) {
Item x = ItemGenerator.CreateItem(rewardType,"legendary",player.Level);
QuestReward.Add(x);
}
QuestNPCName = GetComponent<NPCDialog>().NpcName;
CheckRequirements();
}

public void OnEnable(){
Messenger<string>.AddListener("MonsterKilled",AddMobsKilled);
}

public void OnDisable(){
Messenger<string>.RemoveListener("MonsterKilled",AddMobsKilled);
}

void Update() {
if(isAccepted && !isFinished){
questTracker = "";
if(numberToKill > 0){
CheckForMobs();
questTracker += ToolTipStyle.Break;
}

if(numberToObtain > 0){
CheckForItems();
questTracker += ToolTipStyle.Break;
}

if(talkingCompletesQuest){
CheckForTalk();
}

CheckForCompletion();
}
else if(isFinished){
string addS = numberToKill > 1 ? "s" : "";
string txtDone = talkDone ? "Done" : "Not Done";
questTracker = "";
if(numberToKill > 0){
questTracker = string.Format("{0}{1} Killed: {2} of {3}",nameOfMob,addS,numberKilled,numberToKill);
}

if(numberToObtain > 0){
if(questTracker != "")
questTracker += ToolTipStyle.Break;
questTracker += string.Format("{0} Gained: {1} of {2}",nameOfItem,numberObtained,numberToObtain);
}

if(talkingCompletesQuest){
if(questTracker != "")
questTracker += ToolTipStyle.Break;
questTracker += string.Format("Talked to {0} : {1}",nameOfNPCtoTalkTo,txtDone);
}
}
}

private void AddMobsKilled(string mobName){
if(isAccepted && !isFinished){
if(mobName.Contains (nameOfMob)){
numberKilled += 1;
if(numberKilled > numberToKill){
numberKilled = numberToKill;
}
}
}
}

private void CheckForMobs(){
if(numberKilled >= numberToKill)
killDone = true;

string addS = numberToKill > 1 ? "s" : "";
questTracker = string.Format("{0}{1} Killed: {2} of {3}",nameOfMob,addS,numberKilled,numberToKill);
}

private void CheckForItems(){
numberObtained = 0;

for (int i = 0; i < player.Inventory.Count; i++) {
if(player.Inventory[i].Name == nameOfItem){
numberObtained = player.Inventory[i].CurStacks;
if(player.Inventory[i].CurStacks > numberToObtain){
player.Inventory[i].CurStacks = numberToObtain;
}
}
}

if(numberObtained >= numberToObtain){
itemDone = true;
}

questTracker += string.Format("{0} Gained: {1} of {2}",nameOfItem,numberObtained,numberToObtain);
}

private void CheckForTalk(){
string txtDone = talkDone ? "Done" : "Not Done";
questTracker += string.Format("Talked to {0} : {1}",nameOfNPCtoTalkTo,txtDone);
}

private void CheckForCompletion(){
bool completed = true;
if(numberToKill > 0 && !killDone)
completed = false;
if(numberToObtain > 0 && !itemDone)
completed = false;
if(talkingCompletesQuest && !talkDone)
completed = false;

if(completed){
isComplete = true;
}
}

private int numberOfQuestsNeeded = 0;
private int numberOfQuestsFound = 0;

public void CheckRequirements() {

numberOfQuestsNeeded = QuestIDReq.Length;

//Check Level
if(player.Level >= QuestLevelReq){
requirementStatus = RequirementsStatus.Level;
}

foreach(int nqID in QuestIDReq){
foreach(NPCQuest nq in player.questsComplete){
if(nq.QuestID == nqID){
numberOfQuestsFound = numberOfQuestsFound + 1;
}
}
}

if(numberOfQuestsFound >= numberOfQuestsNeeded){
if(requirementStatus == RequirementsStatus.Level)
requirementStatus = RequirementsStatus.All;
else
requirementStatus = RequirementsStatus.Quests;
}

numberOfQuestsFound = 0;

}

//FOR GUI

public string QuestInfo(){
string questInfo = ToolTipStyle.Blue + QuestName + ToolTipStyle.EndColor
+ ToolTipStyle.Break + QuestNPCName;
return questInfo;
}

public string QuestRewardString(){
string questRewardString = "Exp: " + QuestExpReward.ToString() + " Gold: " + QuestGoldReward.ToString();
return questRewardString;
}

public void CancelQuest(){
talkDone = killDone = itemDone = isComplete = isAccepted = false;
numberKilled = numberObtained = 0;
Debug.Log("Quest Canceled");
player.QuestsInProgress.Remove(this);
}

public void LoadFinishedQuest(){
if(player == null){
player = GameObject.FindGameObjectWithTag("Player").GetComponent<PlayerNew>();
}

foreach(NPCQuest nq in player.questsComplete){
if (nq.QuestID == this.QuestID) return;
}

player.questsComplete.Add(this);
}

public void LoadInProgressQuest(){
if(player == null){
player = GameObject.FindGameObjectWithTag("Player").GetComponent<PlayerNew>();
}

if(player.QuestsInProgress.Count > 0){
foreach(NPCQuest nq in player.QuestsInProgress){
if (nq.QuestID == this.QuestID) return;
}
}

player.QuestsInProgress.Add(this);
}
}

public enum RequirementsStatus {
None,
Quests,
Level,
All
}


using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class MonsterAI : MonoBehaviour {

private PlayerNew player;
public string NameOfMob = "Cube";
public int LevelOfMob = 1;
public  MonsterType monsterType = MonsterType.Normal;
public int Damage = 10;
public int expValue = 30;

public float RunSpeed = 2;
public float AttacksPerSecond;
private float OriginalAttacksPerSecond;
public float timeSinceLastAttack;

public int MonsterHealth;

public string NumberOfItemsToDrop = "random";
public string ItemTypesToDrop = "random";
public string ItemsDroppedRarity = "random";

//AI
public bool inCombat;
public bool isDead;
public bool EnableCombat;

//sgo
public GlobalPrefabs globalPrefabs;

//From Player Procs
public bool isUseless; //Won't do anything
public bool isStunned;	//can't move
public bool isSlowed;	//Attack Speed is slowed
public float amountSlowedBy;	//Attack speed reduction
public bool isKnockedBack;	//If knocked back( so can't chain knockback)
public List<string> currentDots = new List<string>();

void Start(){
QuestItemsClasses.AddAllItems();
if(player == null){
player = GameObject.FindGameObjectWithTag("Player").GetComponent<PlayerNew>();
}

if(globalPrefabs == null){
//	globalPrefabs = GameObject.FindGameObjectWithTag("GameMaster").GetComponent<GlobalPrefabs>();
}

OriginalAttacksPerSecond = AttacksPerSecond;
}

void Update () {

timeSinceLastAttack += Time.deltaTime;

//		float curHealth = GetComponent<Health>().CurrentHealth;
//
//		if(curHealth <= 0 ){
//			MonsterHealth = 0;
//			isDead = true;
//		}
//
if(isDead){
player.AddExp(expValue);
string nameOfMobToSend = monsterType == MonsterType.Normal ? NameOfMob : "BOSS" + NameOfMob;
Messenger<string>.Broadcast("MonsterKilled",nameOfMobToSend);
//Destroy all floating text attached to this
FloatingTextGUI[] floatingTexts = GetComponentsInChildren<FloatingTextGUI>();
for (int i = 0; i < floatingTexts.Length; i++) {
Destroy(floatingTexts[i].gameObject,0.5f);
}
//死亡掉落物品
DropLoot();
Destroy(gameObject);

}
else{
if(inCombat){
EnableCombat =true;
}
else {
EnableCombat = false;
}

if(isStunned){
EnableCombat = false;
}

if(isUseless){
return;
}

if(EnableCombat){
float angleToTarget = Mathf.Atan2((player.transform.position.x - transform.position.x), (player.transform.position.z - transform.position.z)) * Mathf.Rad2Deg;
transform.eulerAngles = new Vector3(0,angleToTarget, 0);

if(Vector3.Distance (transform.position,player.transform.position) > 2){
transform.position = Vector3.MoveTowards(transform.position, player.transform.position, RunSpeed * Time.deltaTime);
}

bool canDealDamage = timeSinceLastAttack > 1 / AttacksPerSecond ? true : false;

if(canDealDamage){
timeSinceLastAttack = 0;
PlayerHealth php = player.GetComponent<PlayerHealth>();
if(php == null) Debug.Log ("No player health");
DealDamage(php);
canDealDamage = false;
}
}
}
}

public void DropLoot(){
Debug.Log("9999DropLoot,notsee9999");
GameObject loot = GameObject.FindGameObjectWithTag("ItemSpawner");
//		Debug.Log("loot"+loot);
loot.GetComponent<ItemSpawner>().positionToSpawn = transform.position;
//
//		if(ItemsDroppedRarity != null)
//			loot.GetComponent<ItemSpawner>().chestRarity = ItemsDroppedRarity;
//
//		if(ItemTypesToDrop != null)
//			loot.GetComponent<ItemSpawner>().chestSpawnType = ItemTypesToDrop;
//
//		if(NumberOfItemsToDrop != null)
//			loot.GetComponent<ItemSpawner>().itemsInChest = NumberOfItemsToDrop;
//
//		loot.GetComponent<ItemSpawner>().chestItemLevel = LevelOfMob;
//
//		//Clear loot and populate with random items
//		loot.GetComponent<ItemSpawner>().PopulateChest();
//
//		//40% Chance to drop gold
//		int amountOfGold = Random.Range(100*LevelOfMob,1000*LevelOfMob+1);
//		int randomlyAddGold = Random.Range (0,101);
//		if(randomlyAddGold > 60) {
//			loot.GetComponent<ItemSpawner>().loot.Add (StaticItems.GoldItem(amountOfGold));
//		}

ItemSpawner lootOfMob = loot.GetComponent<ItemSpawner>();
HandleQuestLoot(lootOfMob);

//Finally, spawn all the items
loot.GetComponent<ItemSpawner>().SpawnItems();

}

void HandleQuestLoot(ItemSpawner lootOfMob){
Debug.Log("HandleQuestLoot");
bool dropLoot = false;
int questIndex = 1000;
Debug.Log("player.QuestsInProgress.Count"+player.QuestsInProgress.Count);
for (int i = 0; i < player.QuestsInProgress.Count; i++) {
Debug.Log("player.QuestsInProgress[i].numberToKill"+player.QuestsInProgress[i].numberToKill);
if(player.QuestsInProgress[i].numberToKill > 0){
Debug.Log("player.QuestsInProgress[i].nameOfMobThatDropsItem="+player.QuestsInProgress[i].nameOfMobThatDropsItem);
Debug.Log("player.QuestsInProgress[i].nameOfMobThatDropsItem.Contains(NameOfMob)="+player.QuestsInProgress[i].nameOfMobThatDropsItem.Contains(NameOfMob));

if(player.QuestsInProgress[i].nameOfMobThatDropsItem.Contains(NameOfMob)){
Debug.Log("player.QuestsInProgress[i].itemDone="+player.QuestsInProgress[i].itemDone);
if(!player.QuestsInProgress[i].itemDone){
Debug.Log("check dropLoot="+dropLoot);
dropLoot = true;
questIndex = i;
Debug.Log("questIndex int for"+questIndex);

}
}
}
}

if(dropLoot){
Debug.Log("questIndex=="+questIndex);
Item QuestItemToAdd = MobQuestItem(questIndex);
Debug.Log("QuestItemToAdd.Name"+QuestItemToAdd.Name);
//create a new instance
QuestItemToAdd = new QuestItem(QuestItemToAdd.Name,QuestItemToAdd.Description,QuestItemToAdd.CurStacks,QuestItemToAdd.MaxStacks,QuestItemToAdd.Icon);

if(QuestItemToAdd != null)
lootOfMob.loot.Add (QuestItemToAdd);
}
}

Item MobQuestItem(int questIndex) {
Debug.Log (QuestItemsClasses.AllQuestItems.Count);
for (int i = 0; i < QuestItemsClasses.AllQuestItems.Count; i++) {
Debug.Log("player.QuestsInProgress[questIndex].nameOfItem"+player.QuestsInProgress[questIndex].nameOfItem);
Debug.Log("QuestItemsClasses.AllQuestItems[i].Name=="+QuestItemsClasses.AllQuestItems[i].Name);
//If the name of the quest item is the name of the quest item
if(player.QuestsInProgress[questIndex].nameOfItem == QuestItemsClasses.AllQuestItems[i].Name){

return QuestItemsClasses.AllQuestItems[i];
}
}

return null;
}

//Deal Damage
void DealDamage(PlayerHealth hp){
if(hp){

hp.DealDamage((int)Damage);

player.playerState = PlayerState.Combat;
player.CheckForExitCombat();
}
}

//Procs
//KnockBack
public void KnockBackSelf(){
StartCoroutine("KnockBack");
}
private IEnumerator KnockBack(){
StopCoroutine("KnockBack");
isUseless = true;
isKnockedBack = true;

GameObject dmgTxt = (GameObject)Instantiate(globalPrefabs.floatingDamageText);
dmgTxt.transform.parent = this.transform;
FloatingTextGUI dmgText = dmgTxt.GetComponent<FloatingTextGUI>();
dmgText.SetDmgInfo(ToolTipStyle.Purple + "Knockback!" + ToolTipStyle.EndColor,transform.position);

yield return new WaitForSeconds(0.5f);
isKnockedBack = false;
isUseless = false;
}

//Stun
public void StunSelf(float timeToStunSelf){
StartCoroutine("Stun",timeToStunSelf);
}
private IEnumerator Stun(float timeToStun){
StopCoroutine("Stun");

GameObject dmgTxt = (GameObject)Instantiate(globalPrefabs.floatingDamageText);
dmgTxt.transform.parent = this.transform;
FloatingTextGUI dmgText = dmgTxt.GetComponent<FloatingTextGUI>();
dmgText.SetDmgInfo(ToolTipStyle.Purple + "Stunned!" + ToolTipStyle.EndColor,transform.position);

isStunned = true;
yield return new WaitForSeconds(timeToStun);
isStunned = false;
}

//Slow
public void SlowAttackSpeed(float amountToSlow){
AttacksPerSecond = OriginalAttacksPerSecond;
StartCoroutine("Slow",amountToSlow);
}
private IEnumerator Slow(float amountToReduceBy){//e.g. 0.3f = 30% attack speed lost
StopCoroutine("Slow");

GameObject dmgTxt = (GameObject)Instantiate(globalPrefabs.floatingDamageText);
dmgTxt.transform.parent = this.transform;
FloatingTextGUI dmgText = dmgTxt.GetComponent<FloatingTextGUI>();
dmgText.SetDmgInfo(ToolTipStyle.Purple + "Attack slowed!" + ToolTipStyle.EndColor,transform.position);

AttacksPerSecond += amountToReduceBy * AttacksPerSecond;
yield return new WaitForSeconds(3.0f);
AttacksPerSecond = OriginalAttacksPerSecond;
}

//DOT
public void UseDot(string dotName, int damage,int ticks, float timeBetweenTicks){
for (int i = 0; i < currentDots.Count; i++) {
if(currentDots[i].Contains(dotName)){
Debug.Log ("Same DOT, will not cast");
return;
}
}

StartCoroutine(DoDot(dotName,ticks,damage, timeBetweenTicks));
}

private IEnumerator DoDot(string dotName,int damage, int ticks, float timeBetweenTicks){
currentDots.Add(dotName);
for (int i = 0; i < ticks; i++) {
this.GetComponent<Health>().CurrentHealth -= damage;

GameObject dmgTxt = Instantiate(globalPrefabs.floatingDamageText) as GameObject;
dmgTxt.transform.parent = this.transform;
FloatingTextGUI dmgText = dmgTxt.GetComponent<FloatingTextGUI>();
dmgText.SetDmgInfo(ToolTipStyle.Purple + damage.ToString() + ToolTipStyle.EndColor,transform.position);

yield return new WaitForSeconds(timeBetweenTicks);
}
currentDots.Remove(dotName);
}

}

public enum MonsterType {
Normal,
MiniBoss,
Boss
}


运行后的效果



















EnemyController.cs中添加


monsterDeadAI中的nameOfMobToSend暂时测试直接写入,后面会改为通用。

杀怪任务修改完毕。。。。。。。。。。。。。。。。。。。。

在EnemyController中添加 privateMonsterAI Monsterai;

在void Start () {}中添加 Monsterai=this.GetComponent<MonsterAI>();

void MonsterDeadAI(){}中修改代码为

string nameOfMobToSend=Monsterai.NameOfMob;

Messenger<string>.Broadcast("MonsterKilled",nameOfMobToSend);





注释掉void Update (){}中的

// floatcurHealth = GetComponent<Health>().CurrentHealth;

//

// if(curHealth<= 0 ){

// MonsterHealth= 0;

// isDead= true;

// }

//

修改PlayerBase中LevelUpAnimation方法,确保只有一种升级












看看player.QuestsInProgress[i].nameOfMobThatDropsItem这个东东的值是什么,


























一口气贴了这么多东西,其实这是我一周时间写的代码和调试信息,而且用到的类也是一个成熟的任务系统,我只是做了整合,

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class NPCDialog : MonoBehaviour {
public string Title;
public string NpcName;
public TextMesh npcNameLevel;
public GameObject npcBorder;
public bool isVendor;
public bool isBlacksmith;
public Light HighlightLight;
public NPCVendor vendor;
public NPCBlacksmith blacksmith;
public GUISkin mySkin;
private PlayerNew player;
public bool _isNear;
public string[] npcText;
public string[] npcTextOrig;
public int textNum;
public string[] buttonText = new string[2];
public int buttonTextNum;
public List<NPCQuest> quests = new List<NPCQuest>();	//Quests
public int OptionNumber = 0;

public TextMesh hasQuestText;
private float distToBeActive = 30;

// Use this for initialization
void Start () {

if(player == null){

player = GameObject.FindGameObjectWithTag("Player").GetComponent<PlayerNew>();
Debug.Log("player.transform.position.x"+player.transform.position.x);
Debug.Log("player.transform.position.y"+player.transform.position.y);
Debug.Log("player.transform.position.z"+player.transform.position.z);
}
npcTextOrig = npcText;
textNum = 0;
if(HighlightLight != null)
HighlightLight.enabled = false;
if(npcNameLevel != null)
npcNameLevel.text = NpcName;

vendor = GetComponent<NPCVendor>();
if(vendor != null) isVendor = true; else isVendor = false;

blacksmith = GetComponent<NPCBlacksmith>();
if(blacksmith != null) isBlacksmith = true; else isBlacksmith = false;

if(string.IsNullOrEmpty(buttonText[0]))
buttonText[0] = "Next";

if(string.IsNullOrEmpty(buttonText[1]))
buttonText[0] = "Close";
}

void Update(){
float viewDist = Vector3.Distance(player.transform.position, transform.position);

if(NPCDialogGUI.openedNPCDialog != null && NPCDialogGUI.openedNPCDialog == this)
if(viewDist > 7 || player.playerState != PlayerState.NPCDialog)
CloseDialog();

var allQuests = GetComponents<NPCQuest>();
if(allQuests.Length > 0) //if we have quests
{
CheckQuests();
if(quests.Count > 0){
//If has quests and one or more in progress, show grey !
for (int i = 0; i < quests.Count; i++) {
if(quests[i].isAccepted)
hasQuestText.text = ToolTipStyle.Grey + ToolTipStyle.Bold +  "!" + ToolTipStyle.EndBold + ToolTipStyle.EndColor;
}

//If has quests but none accepted or completed, show yellow !
for (int i = 0; i < quests.Count; i++) {
if(!quests[i].isAccepted)
hasQuestText.text = ToolTipStyle.Yellow + ToolTipStyle.Bold +  "!" + ToolTipStyle.EndBold + ToolTipStyle.EndColor;
}

//If has quests and one or more complete, show yellow ?
for (int i = 0; i < quests.Count; i++) {
if(quests[i].isComplete)
hasQuestText.text = ToolTipStyle.Yellow + ToolTipStyle.Bold +  "?" + ToolTipStyle.EndBold + ToolTipStyle.EndColor;
}
}
else if(isVendor){
hasQuestText.text = "$";
}
else {
hasQuestText.text = "";
}
}

if(viewDist < distToBeActive){
npcNameLevel.text = NpcName;
npcBorder.SetActive(true);
}else{
npcNameLevel.text = "";
npcBorder.SetActive(false);

if(quests.Count > 0)
hasQuestText.text = "";
}
}

public void CompleteQuest(NPCQuest quest){
if(player.Inventory.Count + quest.QuestReward.Count  <= player.MaxInventorySpace){

for (int i = 0; i < quest.QuestReward.Count; i+=0) {
bool addedItem = player.AddItem(quest.QuestReward[i]);
if(addedItem){
quest.QuestReward.RemoveAt(i);
}
else {
Debug.Log ("Stack is full");
}
}

if(quest.QuestReward.Count == 0){
player.AddExp(quest.QuestExpReward);
player.ModifyGold(quest.QuestGoldReward);
quest.isFinished = true;
player.questsComplete.Add(quest);

if(quest.qego != null && !quest.EnableQuestGOPerm)
quest.qego.DisableGameObjects();
if(quest.numberToObtain > 0){
for (int i = 0; i < player.Inventory.Count; i++) {
if(player.Inventory[i].Name == quest.nameOfItem){
player.Inventory[i].CurStacks -= quest.numberToObtain;
if(player.Inventory[i].CurStacks <= 0)
player.Inventory.RemoveAt(i);
}
}
}

player.QuestsInProgress.Remove(quest);
EnterDialog();
}
}
else {
Debug.Log("Inventory is Full!");
}

}

void CheckQuests(){

npcText = npcTextOrig;
var _quests = GetComponents<NPCQuest>();
quests = new List<NPCQuest>();

//Check this NPCs quests
foreach(NPCQuest nq in _quests){
nq.CheckRequirements();
if(nq.talkingCompletesQuest && nq.isAccepted && NpcName.Contains(nq.nameOfNPCtoTalkTo)){
nq.talkDone = true;
}
if(!nq.isFinished && nq.requirementStatus != RequirementsStatus.None && nq.requirementStatus != RequirementsStatus.Level)
quests.Add(nq);
}

//Check player quests
foreach(NPCQuest nq in player.QuestsInProgress ){
nq.CheckRequirements();

if(nq.talkingCompletesQuest && !nq.talkDone &&  NpcName.Contains(nq.nameOfNPCtoTalkTo)){
npcText = nq.npcResponse;
OptionNumber = 1;	//Force Conversation
}
}
}

public void EnterDialog(){
if(player.playerState != PlayerState.Normal) return;

player.playerState = PlayerState.NPCDialog;
OptionNumber = 0;
textNum = 0;
CheckQuests();
NPCDialogGUI.openedNPCDialog = this;
Messenger.Broadcast ("DisplayNPCWindow");
}

public void CloseDialog(){
player.playerState = PlayerState.Normal;
Messenger.Broadcast ("CloseNPCWindow");
}

void OnTriggerEnter(Collider other){
//		if(other.CompareTag("Player") && other.GetType() != typeof(SphereCollider) && !_isNear){
//			EnterDialog();
//		}
CheckQuests();
}

void OnTriggerExit(Collider other){
//		if(other.CompareTag("Player") && other.GetType() != typeof(SphereCollider)){
//			CloseDialog();
//		}
}

void OnMouseDown () {
float viewDist = Vector3.Distance(player.transform.position, transform.position);
if(viewDist < 7)
EnterDialog();
}

void OnMouseEnter () {
if(HighlightLight != null)
HighlightLight.enabled = true;
}
void OnMouseExit () {
if(HighlightLight != null)
HighlightLight.enabled = false;
}
}

public enum NpcType {
NPC,
Vendor,
Bank
}
虽然贴出了代码,但说实话,就这么看,估计没人看得懂,而且任务系统还包括一段存储的部分,所以我建议这一篇大家先跳过吧,过段时间我整理一下代码,把整个工程文件发出来,否则这篇真的没法看了。建议大家跳过直接看下一篇。

注意要看上面提供了需要的代码包和任务Npc预制件。






内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐