예제 #1
0
파일: scene.go 프로젝트: sguzwf/ouster
func (scene *Scene) addCreature(creature CreatureInterface, cx ZoneCoord_t, cy ZoneCoord_t, dir Dir_t) {
	pt, err := findSuitablePosition(&scene.Zone, cx, cy, creature.CreatureInstance().MoveMode)
	if err == nil {
		if creature.CreatureClass() == CREATURE_CLASS_MONSTER {
			monster := creature.(*Monster)
			scene.monsterManager.addCreature(monster)
			// pkt = packet.AddMonsterPacket(pMonster, NULL)
			// broadcastPacket(cx, cy, pAddMonsterPacket, pMonster)
		} else if creature.CreatureClass() == CREATURE_CLASS_NPC {
			npc := creature.(*NPC)
			scene.npcManager.addCreature(npc)

			// gcAddNPC := packet.GCAddNPCPacket{}
			// broadcastPacket(pt.x, pt.y, &gcAddNPC)
		}

		scene.Tile(pt.X, pt.Y).addCreature(creature)

		c := creature.CreatureInstance()
		c.X = ZoneCoord_t(pt.X)
		c.Y = ZoneCoord_t(pt.Y)
		c.Dir = dir

		c.Scene = scene
	} else {
		log.Debugln("应该是运行到这里来了,是不是?")
	}
}
예제 #2
0
파일: effect.go 프로젝트: sguzwf/ouster
func (manager EffectManager) heartbeat(now time.Time) {
	for _, eft := range manager.Effects {
		// effectclass := eft.EffectClass()
		effect := eft.EffectInstance()
		if now.After(effect.Deadline) {
			// 删除
			eft.unaffect()
			delete(manager.Effects, effect.ObjectID)
			log.Debugln("effect unaffect...", eft)
		} else {
			if now.After(effect.NextTime) {
				log.Debugln("effect affact...", eft)
				eft.affect()
			}
		}
	}
}
예제 #3
0
파일: packet.go 프로젝트: sguzwf/ouster
func (r *Reader) Read(reader io.Reader) (ret Packet, err error) {
	var id PacketID
	var sz uint32
	var seq uint8

	err = ReadHeader(reader, &id, &sz, &seq)
	if err != nil {
		return
	}
	r.Seq = seq

	log.Debugln("packet header:", id, sz, seq)
	if id >= PACKET_MAX {
		err = errors.New("packet id too large!")
		return
	}

	ret = packetTable[id]
	if ret == nil {
		log.Debugln("reading a not implement packet:", id)
		var buf [500]byte
		raw := RawPacket{
			Id:  id,
			Seq: seq,
		}
		if sz > uint32(len(buf)) {
			err = errors.New("too large raw packet")
			return
		}
		_, err = reader.Read(buf[:sz])
		if err != nil {
			return
		}
		copy(raw.Data, buf[:sz])
		err = NotImplementError{}
		return
	}

	err = ret.Read(reader, r.Code)
	if ret.PacketSize() != sz {
		log.Warnf("packet not read clean: id=%d, sz=%d, read=%d", id, sz, ret.PacketSize())
	}
	return
}
예제 #4
0
파일: player.go 프로젝트: sguzwf/ouster
func InitPlayer(player *Player, conn net.Conn) {
	player.PlayerStatus = GPS_BEGIN_SESSION
	player.conn = conn

	read := make(chan packet.Packet, 1)
	write := make(chan packet.Packet, 1)
	player.send = write
	player.client = read

	go func() {
		reader := packet.NewReader()
		player.packetReader = reader
		for {
			data, err := reader.Read(player.conn)
			if err != nil {
				if _, ok := err.(packet.NotImplementError); ok {
					log.Errorln("读到一个未实现的包:", data.PacketID())
				} else {
					if err == io.EOF {
						log.Infoln("后台gouroutine读客户端失败了:", err)
						player.conn.Close()
						// 关闭读channel会使得agent的goroutine退出,回收资源
						close(read)
						return
					} else {
						log.Errorln("这是一个严重的错误:", err)
						return
					}
				}
			}
			log.Debugln("读到了一个packet:", data)
			read <- data
		}
	}()

	go func() {
		writer := packet.NewWriter()
		player.packetWriter = writer
		for {
			pkt, ok := <-write
			if !ok {
				// 关闭使读goroutine退出
				player.conn.Close()
				return
			}
			log.Debugf("write channel get a pkt: %#v\n", pkt)
			err := writer.Write(player.conn, pkt)
			if err != nil {
				log.Errorln(err)
				continue
			}
		}
	}()
}
예제 #5
0
파일: agent.go 프로젝트: sguzwf/ouster
func (agent *Agent) Loop() {
	heartbeat := time.Tick(200 * time.Millisecond)
	for {
		select {
		case msg, ok := <-agent.client:
			if !ok {
				log.Debugln("客户端关了")
				return
			}
			log.Debugln("agent收到一个packet:", msg)
			agent.handleClientMessage(msg)
		case <-heartbeat:
			if agent.PlayerCreatureInterface != nil {
				agent.heartbeat()
			}
		case f, _ := <-agent.computation:
			f()
		}
	}
}
예제 #6
0
파일: vampire.go 프로젝트: sguzwf/ouster
func (vampire *Vampire) PCInfo() data.PCInfo {
	if vampire == nil || vampire.Scene == nil {
		log.Errorln("f**k...Scene为空谁让你调这个函数了?")
		return nil
	}

	ret := &data.PCVampireInfo{
		ObjectID: vampire.ObjectID,
		Name:     vampire.Name,
		Level:    vampire.Level,
		Sex:      vampire.Sex,

		BatColor:  vampire.BatColor,
		SkinColor: vampire.SkinColor,

		Alignment: vampire.Alignment,
		Rank:      vampire.Rank,
		RankExp:   vampire.RankExp,

		Exp:   vampire.Exp,
		Fame:  vampire.Fame,
		Gold:  vampire.Gold,
		Sight: vampire.Sight,
		Bonus: vampire.Bonus,
		// HotKey:       vampire.HotKey,
		SilverDamage: vampire.SilverDamage,

		Competence: vampire.Competence,
		GuildID:    vampire.GuildID,

		GuildMemberRank: vampire.GuildMemberRank,
		UnionID:         vampire.UnionID,

		AdvancementLevel:   vampire.AdvancementLevel,
		AdvancementGoalExp: vampire.AdvancementGoalExp,

		ZoneID: vampire.Scene.ZoneID,
		ZoneX:  Coord_t(vampire.X),
		ZoneY:  Coord_t(vampire.Y),
	}

	log.Debugln("run here.......")
	ret.STR[ATTR_CURRENT] = vampire.STR[ATTR_CURRENT]
	ret.STR[ATTR_MAX] = vampire.STR[ATTR_MAX]
	ret.DEX[ATTR_CURRENT] = vampire.DEX[ATTR_CURRENT]
	ret.DEX[ATTR_MAX] = vampire.DEX[ATTR_MAX]
	ret.INI[ATTR_CURRENT] = vampire.INI[ATTR_CURRENT]
	ret.INI[ATTR_MAX] = vampire.INI[ATTR_MAX]
	ret.HP[ATTR_CURRENT] = vampire.HP[ATTR_CURRENT]
	ret.HP[ATTR_MAX] = vampire.HP[ATTR_MAX]

	return ret
}
예제 #7
0
파일: zone.go 프로젝트: sguzwf/ouster
func (zone *Zone) moveCreatureBroadcast(creature CreatureInterface, x1 ZoneCoord_t, y1 ZoneCoord_t, x2 ZoneCoord_t, y2 ZoneCoord_t) {
	inst := creature.CreatureInstance()

	for ix, endx := max(0, int(x2)-int(MaxViewportWidth)-1), min(int(zone.Width)-1, int(x2)+int(MaxViewportWidth)+1); ix <= endx; ix++ {
		for iy, endy := max(0, int(y2)-int(MaxViewportUpperHeight)-1), min(int(zone.Height)-1, int(y2)+int(MaxViewportLowerHeight)+1); iy <= endy; iy++ {
			tile := zone.Tile(ix, iy)
			for _, obj := range tile.Objects {
				if agent, ok := obj.(*Agent); ok {
					pc := agent.PlayerCreatureInstance()
					log.Debugf("agent id=%d x=%d y=%d\n", pc.ObjectID, ix, iy)
					prevVS := getVisionState(pc.X, pc.Y, x1, y1)
					currVS := getVisionState(pc.X, pc.Y, x2, y2)

					if prevVS == OUT_OF_SIGHT && currVS == IN_SIGHT {
						if monster, ok := creature.(*Monster); ok {
							agent.sendPacket(&packet.GCAddMonster{
								ObjectID:    monster.ObjectID,
								MonsterType: monster.MonsterType,
								MonsterName: monster.Name,
								MainColor:   monster.MainColor,
								SubColor:    monster.SubColor,
								X:           Coord_t(monster.X),
								Y:           Coord_t(monster.Y),
								Dir:         monster.Dir,
								// EffectInfo  []EffectInfo
								CurrentHP: monster.HP[ATTR_CURRENT],
								MaxHP:     monster.HP[ATTR_MAX],
								// FromFlag		byte
							})
						}
					} else if prevVS == IN_SIGHT && currVS == IN_SIGHT {
						move := &packet.GCMovePacket{
							ObjectID: inst.ObjectID,
							X:        Coord_t(inst.X),
							Y:        Coord_t(inst.Y),
							Dir:      inst.Dir,
						}
						agent.sendPacket(move)
						log.Debugln("broadcast a GCMovePacket", move)
					} else if prevVS == IN_SIGHT && currVS == OUT_OF_SIGHT {
						agent.sendPacket(&packet.GCDeleteObjectPacket{
							ObjectID: inst.ObjectID,
						})
					}

				}
			}
		}
	}
}
예제 #8
0
파일: scene.go 프로젝트: sguzwf/ouster
func (scene *Scene) getCreature(objectID ObjectID_t) CreatureInterface {
	monster := scene.monsterManager.getCreature(objectID)
	if monster != nil {
		return monster
	}

	agent, ok := scene.players[objectID]
	if ok {
		return agent
	}

	log.Debugln("没有找到creature")
	// pCreature = m_pNPCManager->getCreature(objectID);

	return nil
}
예제 #9
0
func (sc SharpChakram) ExecuteToSelf(skill *packet.CGSkillToSelfPacket, agent *Agent) {
	// weapon := agent.getWearItem(OUSTER_WEAR_RIGHTHAND)
	// if weapon == nil {
	// 	// TODO
	// 	return
	// }

	// sc.Check(skill.SkillType, agent)

	var input SkillInput
	var output SkillOutput
	sc.ComputeOutput(&input, &output)

	pc := agent.PlayerCreatureInstance()

	eft := new(EffectSharpChakram)
	eft.Deadline = time.Now().Add(time.Duration(output.Duration) * time.Millisecond)
	eft.Bonus = uint32(output.Damage)
	pc.addEffect(eft)
	pc.setFlag(eft.EffectClass())

	agent.sendPacket(&packet.GCSkillToSelfOK1{
		SkillType: skill.SkillType,
		CEffectID: skill.CEffectID,
		Duration:  uint16(output.Duration),
	})

	log.Debugln("运行到这里  发送SkillToSelfOK1...")

	pc.Scene.broadcastPacket(pc.X, pc.Y, &packet.GCSkillToSelfOK2{
		ObjectID:  pc.ObjectID,
		SkillType: skill.SkillType,
		Duration:  Duration_t(output.Duration),
	}, agent)

	pc.Scene.broadcastPacket(pc.X, pc.Y, &packet.GCAddEffect{
		ObjectID: pc.ObjectID,
		EffectID: EffectID_t(eft.EffectClass()),
		Duration: Duration_t(output.Duration),
	}, agent)

	// skillslot := pc.SkillSlot[skill.SkillType]
	// skillslot.setRunTime(output.Delay)
}
예제 #10
0
파일: main.go 프로젝트: sguzwf/ouster
func serve(conn net.Conn) {
	defer conn.Close()

	reader := packet.NewReader()
	writer := packet.NewWriter()

	for {
		pkt, err := reader.Read(conn)
		if err != nil {
			if _, ok := err.(packet.NotImplementError); !ok {
				log.Errorln("read packet error in loginserver's serve:", err)
				return
			}
		}

		log.Debugln("read a packet: ", pkt.PacketID())

		switch pkt.PacketID() {
		case packet.PACKET_CL_GET_WORLD_LIST:
			writer.Write(conn, packet.LCWorldListPacket{})
		case packet.PACKET_CL_LOGIN:
			writer.Write(conn, packet.LCLoginOKPacket{})
		case packet.PACKET_CL_SELECT_SERVER:
			writer.Write(conn, &packet.LCPCListPacket{})
		case packet.PACKET_CL_SELECT_WORLD:
			writer.Write(conn, &packet.LCServerListPacket{})
		case packet.PACKET_CL_VERSION_CHECK:
			writer.Write(conn, packet.LCVersionCheckOKPacket{})
		case packet.PACKET_CL_SELECT_PC:
			reconnect := &packet.LCReconnectPacket{
				Ip:   config.GameServerIP,
				Port: 9998,
				Key:  82180,
			}
			writer.Write(conn, reconnect)
			return
		default:
			log.Errorf("get a unknow packet: %d\n", pkt.PacketID())
		}
	}
}
예제 #11
0
func LoadPlayerCreature(name string, typ packet.PCType) (ptr PlayerCreatureInterface, zoneID ZoneID_t, err error) {
	fileName := config.DataDir + name
	log.Debugln("load文件", fileName)
	f, err := os.Open(fileName)
	if err != nil {
		return
	}
	defer f.Close()

	decoder := json.NewDecoder(f)

	switch typ {
	case packet.PC_VAMPIRE:
		return loadVampire(decoder)
	case packet.PC_OUSTER:
		return loadOuster(decoder)
	case packet.PC_SLAYER:
		return loadSlayer(decoder)
	}
	return nil, 0, errors.New("player type error!")
}
예제 #12
0
func loadVampire(decoder *json.Decoder) (vampire *Vampire, zoneID ZoneID_t, err error) {
	var pcInfo data.PCVampireInfo
	err = decoder.Decode(&pcInfo)
	if err != nil {
		return
	}

	vampire = new(Vampire)
	vampire.Init()
	vampire.Name = pcInfo.Name
	vampire.Level = pcInfo.Level
	vampire.Sex = pcInfo.Sex
	vampire.SkinColor = pcInfo.SkinColor
	vampire.Alignment = pcInfo.Alignment
	vampire.STR = pcInfo.STR
	vampire.DEX = pcInfo.DEX
	vampire.INI = pcInfo.INI
	vampire.HP[ATTR_MAX] = pcInfo.HP[ATTR_MAX]
	vampire.HP[ATTR_CURRENT] = pcInfo.HP[ATTR_CURRENT]
	vampire.Rank = pcInfo.Rank
	vampire.RankExp = pcInfo.RankExp
	vampire.Exp = pcInfo.Exp
	vampire.Fame = pcInfo.Fame
	vampire.Sight = pcInfo.Sight
	vampire.Bonus = pcInfo.Bonus
	vampire.Competence = pcInfo.Competence
	vampire.GuildMemberRank = pcInfo.GuildMemberRank
	vampire.AdvancementLevel = pcInfo.AdvancementLevel

	zoneID = pcInfo.ZoneID
	vampire.X = ZoneCoord_t(pcInfo.ZoneX)
	vampire.Y = ZoneCoord_t(pcInfo.ZoneY)

	if vampire.X == 0 || vampire.Y == 0 {
		log.Debugln("不科学呀", vampire.X, vampire.Y)
	}
	return
}
예제 #13
0
파일: api.go 프로젝트: sguzwf/ouster
func Read(reader io.Reader, code uint8) (ret Packet, seq uint8, err error) {
	var id PacketID
	var sz uint32

	err = ReadHeader(reader, &id, &sz, &seq)
	if err != nil {
		return
	}

	if id >= PACKET_MAX {
		err = errors.New("packet id too large!")
		return
	}

	ret = packetTable[id]
	if ret == nil {
		log.Debugln("reading a not implement packet:", id)
		var buf [500]byte
		raw := RawPacket{
			Id:  id,
			Seq: seq,
		}
		if sz > uint32(len(buf)) {
			err = errors.New("too large raw packet")
			return
		}
		_, err = reader.Read(buf[:sz])
		if err != nil {
			return
		}
		copy(raw.Data, buf[:sz])
		err = NotImplementError{}
		return
	}

	err = ret.Read(reader, code)
	return
}
예제 #14
0
파일: zone.go 프로젝트: sguzwf/ouster
// moveMonster
func (zone *Zone) moveCreature(creature CreatureInterface, nx ZoneCoord_t, ny ZoneCoord_t, dir Dir_t) {
	inst := creature.CreatureInstance()
	cx := inst.X
	cy := inst.Y

	tile := zone.Tile(int(cx), int(cy))
	newTile := zone.Tile(int(nx), int(ny))

	newTile.addCreature(creature)
	tile.deleteCreature(inst.ObjectID)

	log.Debugf("monster %d move: (%d,%d)->(%d,%d) zone=%p scene=%p\n", inst.ObjectID, cx, cy, nx, ny, zone, inst.Scene)
	log.Debugln("tile:", newTile)

	inst.X = nx
	inst.Y = ny
	inst.Dir = dir

	// checkMine(this, pCreature, nx, ny);
	// checkTrap(this, pCreature);

	zone.moveCreatureBroadcast(creature, cx, cy, nx, ny)
}
예제 #15
0
파일: zone.go 프로젝트: sguzwf/ouster
func (zone *Zone) movePCBroadcast(agent *Agent, x1 ZoneCoord_t, y1 ZoneCoord_t, x2 ZoneCoord_t, y2 ZoneCoord_t) {
	beginX := x2 - ZoneCoord_t(MaxViewportWidth) - 1
	if beginX < 0 {
		beginX = 0
	}
	endX := x2 + ZoneCoord_t(MaxViewportWidth) + 1
	if endX > zone.Width {
		endX = zone.Width
	}
	beginY := y2 - ZoneCoord_t(MaxViewportUpperHeight) - 1
	if beginY < 0 {
		beginY = 0
	}
	endY := y2 + ZoneCoord_t(MaxViewportUpperHeight) + 1
	if endY > zone.Height {
		endY = zone.Height
	}

	for i := beginX; i < endX; i++ {
		for j := beginY; j < endY; j++ {
			tile := zone.Tile(int(i), int(j))
			for _, v := range tile.Objects {
				objectClass := v.ObjectClass()
				if objectClass == OBJECT_CLASS_CREATURE {

					prevVS := getVisionState(x1, y1, ZoneCoord_t(i), ZoneCoord_t(j))
					currVS := getVisionState(x2, y2, ZoneCoord_t(i), ZoneCoord_t(j))

					switch v.(type) {
					case *Monster:
						monster := v.(*Monster)
						// 怪物进入玩家视线
						if prevVS == OUT_OF_SIGHT && currVS == IN_SIGHT {
							agent.sendPacket(&packet.GCAddMonster{
								ObjectID:    monster.ObjectID,
								MonsterType: monster.MonsterType,
								MonsterName: monster.Name,
								// MainColor:   monster.MainColor,
								// SubColor:		monster.SubColor,
								X:   Coord_t(monster.X),
								Y:   Coord_t(monster.Y),
								Dir: monster.Dir,
								// EffectInfo  []EffectInfo
								CurrentHP: monster.HP[ATTR_CURRENT],
								MaxHP:     monster.HP[ATTR_MAX],
								// FromFlag    byte
							})
							log.Debugln("发现了一个怪物...")
							// 把玩家放到怪物的敌人列表中
							monster.addEnemy(agent)
						}
					case *Slayer:
						// pc.sendPacket(packet.GCAddSlayer{})
						slayer := v.(*Slayer)
						if canSee(slayer, agent) {
							// slayer.sendPacket(packet.GCAddSlayer{})
						} else {
							// slayer.sendPacket(packet.GCDeleteObject{})
						}
					case *Vampire:
						vampire := v.(*Vampire)
						if canSee(agent, vampire) {
							if vampire.IsFlag(EFFECT_CLASS_HIDE) {
								// pc.sendPacket(packet.GCAddBurrowingCreaturePacket{
								//     ObjectID: vampire.ObjectID,
								//     Name:     vampire.Name,
								//     X:        vampire.X,
								//     Y:        vampire.Y,
								// })
							} else {
								// pc.sendPacket(packet.GCAddVampire{})
							}
						}
						if canSee(vampire, agent) {
							// TODO:添加或者移除
						}
					case *Ouster:
						ouster := v.(*Ouster)
						if canSee(agent, ouster) {
							// pc.sendPacket(packet.GCAddOuster{})
						}
						if canSee(ouster, agent) {
							// TODO:添加或者移除
						}
					case *NPC:
						// pc.sendPacket(packet.GCAddNPC{})
					}
				} else if objectClass == OBJECT_CLASS_ITEM {
					item := v.(ItemInterface)
					itemClass := item.ItemClass()
					if itemClass == ITEM_CLASS_CORPSE {
						switch v.(type) {
						case *SlayerCorpse:
						// pc.sendPacket(packet.GCAddSlayerCorpse{})
						case *VampireCorpse:
						// pc.sendPacket(packet.GCAddVampireCorpse{})
						case *OusterCorpse:
						// pc.sendPacket(packet.GCAddOusterCorpse{})
						case *MonsterCorpse:
							// pc.sendPacket(packet.GCAddMonsterCorpse{})
						}
					}
				} else if objectClass == OBJECT_CLASS_EFFECT {
					// TODO:...
					// pc.sendPacket(packet.GCAddEffectToTile{})
				}
			}
		}
	}
}
예제 #16
0
파일: effect.go 프로젝트: sguzwf/ouster
func (effect *EffectSharpHail) affect() {
	castCreature := effect.Scene.getCreature(effect.UserObjectID)
	log.Debugln("userObjectID:", effect.UserObjectID, castCreature)
	tile := effect.Scene.Tile(int(effect.X), int(effect.Y))

	for _, obj := range tile.Objects {
		if obj.ObjectClass() != OBJECT_CLASS_CREATURE {
			continue
		}

		creature := obj.(CreatureInterface)

		if !canAttack(castCreature, creature) ||
			creature.CreatureInstance().isFlag(EFFECT_CLASS_COMA) {
			continue
		}

		// if (pCastCreature != NULL && !HitRoll::isSuccess(pCastCreature, pCreature ) ) continue;

		switch obj.(type) {
		case *Monster:
			monster := obj.(*Monster)
			effect.Scene.setDamage(monster, castCreature.(*Agent), Damage_t(effect.Damage)) // SKILL_SHARP_HAIL, NULL, &gcAttackerMI, true, true);
			log.Debugln("sharphail的effect对怪物affect了...")
		}

		// GCModifyInformation gcAttackerMI;
		// GCModifyInformation gcDefenderMI;

		// if (pCreature->isSlayer())
		// 			{
		// 				Slayer* pSlayer = dynamic_cast<Slayer*>(pCreature);
		//
		// 				::setDamage(pSlayer, m_Damage, pCastCreature, SKILL_SHARP_HAIL, &gcDefenderMI, &gcAttackerMI, true, true);
		//
		// 				Player* pPlayer = pSlayer->getPlayer();
		// 				Assert(pPlayer != NULL);
		// 				pPlayer->sendPacket(&gcDefenderMI);
		// 			}
		// 			else if (pCreature->isVampire())
		// 			{
		// 				Vampire* pVampire = dynamic_cast<Vampire*>(pCreature);
		//
		// 				::setDamage(pVampire, m_Damage, pCastCreature, SKILL_SHARP_HAIL, &gcDefenderMI, &gcAttackerMI, true, true);
		//
		// 				Player* pPlayer = pVampire->getPlayer();
		// 				Assert(pPlayer != NULL);
		// 				pPlayer->sendPacket(&gcDefenderMI);
		// 			}
		// else if (pCreature->isOusters() && isForce() )
		// {
		// 	Ousters* pOusters = dynamic_cast<Ousters*>(pCreature);
		//
		// 	::setDamage(pOusters, m_Damage, pCastCreature, SKILL_SHARP_HAIL, &gcDefenderMI, &gcAttackerMI, true, true);
		//
		// 	Player* pPlayer = pOusters->getPlayer();
		// 	Assert(pPlayer != NULL);
		// 	pPlayer->sendPacket(&gcDefenderMI);
		// }

		// if (gcAttackerMI.getShortCount() != 0 || gcAttackerMI.getLongCount() != 0 )
		// pCastCreature->getPlayer()->sendPacket(&gcAttackerMI);
	}

	effect.NextTime = effect.NextTime.Add(time.Duration(effect.Tick) * time.Millisecond)
}
예제 #17
0
파일: ai.go 프로젝트: sguzwf/ouster
func (ai *MonsterAI) Deal(pEnemy CreatureInterface, currentTime time.Time) {
	for i, pDirective := range ai.DirectiveSet.Directives {
		if ai.checkDirective(pDirective, pEnemy) {
			switch pDirective.Action {
			case DIRECTIVE_ACTION_APPROACH:
				log.Debugln("动作是approach", i)
				ai.approach(pEnemy)
			case DIRECTIVE_ACTION_FLEE:
				log.Debugln("动作是逃跑")
				if !flee(pEnemy) {
					ai.setMoveRule(MOVE_RULE_NORMAL)
					rValue := ai.useSkill(pEnemy, SKILL_ATTACK_MELEE, 100)
					if rValue != 0 {
						ai.approach(pEnemy)
					}
				}
			case DIRECTIVE_ACTION_USE_SKILL:
				log.Debugln("动作是放技能", i)
				if ai.Body.isFlag(EFFECT_CLASS_BLOCK_HEAD) || ai.Body.isFlag(EFFECT_CLASS_TENDRIL) {
					continue
				}
				parameter := pDirective.Parameter
				ratio := pDirective.Ratio
				rValue := ai.useSkill(pEnemy, SkillType_t(parameter), ratio)
				if rValue != 0 {
					break
				}
				ai.setMoveRule(MOVE_RULE_NORMAL)
			case DIRECTIVE_ACTION_FORGET:
				// log.Debugln("动作是忘记敌人")
				if len(ai.Body.Enemies) != 0 {
					// ai.Body.Enemies = ai.Body.Enemies[1:]
				}
				ai.setMoveRule(MOVE_RULE_NORMAL)
			case DIRECTIVE_ACTION_CHANGE_ENEMY:
				log.Debugln("动作是切换敌人")
				ratio := pDirective.Parameter
				if rand.Intn(100) >= ratio {
					break
				}

				// pNewEnemy := ai.Body.Enemies[0]
				// 从ObjectID得到Creature
				// if pNewEnemy != nil {
				// pEnemy = pNewEnemy
				// } else {
				if len(ai.Body.Enemies) == 0 {
					// ai.Body.addEnemy(pEnemy)
				}
				// }
			case DIRECTIVE_ACTION_MOVE_RANDOM:
				log.Debugln("动作是随机移动")
				ratio := pDirective.Parameter
				if rand.Intn(100) >= ratio {
					break
				}

				// var (
				// x   ZoneCoord_t
				// y   ZoneCoord_t
				// p   TPOINT
				// )

				// x = ai.Body.X
				// y = ai.Body.Y

				// p = getSafeTile(ai.Body.Zone, x, y)

				// if p.x == -1 {
				// break
				// }

				// x1 := p.x
				//								 y1 := p.y
				//								 if x != x1 || y != y1 {
				//										 move(x1, y1)
				//								 }
			case DIRECTIVE_ACTION_WAIT:
				log.Debugln("动作是等待")
				delay := 2 * time.Second
				ai.Body.addAccuDelay(delay)
			case DIRECTIVE_ACTION_FAST_FLEE:
				log.Debugln("动作是快速逃跑")
				result := false
				myX := ai.Body.X
				myY := ai.Body.Y
				nmX := pEnemy.CreatureInstance().X
				nmY := pEnemy.CreatureInstance().Y
				diffX := myX - nmX
				diffY := myY - nmY
				ratio := 5.0 / ZoneCoord_t(abs(int(diffX))+abs(int(diffY)))
				newX := (myX + diffX*ratio)
				newY := (myY + diffY*ratio)

				if isValidZoneCoord(&ai.Body.Scene.Zone, newX, newY) {
					result = ai.Body.Scene.moveFastMonster(ai.Body, myX, myY, newX, newY, SKILL_RAPID_GLIDING)
				}
				if !result {
					break
				}
			case DIRECTIVE_ACTION_SAY:
				log.Debugln("动作是说话")
				// parameter = pDirective.Parameter();
				// GCSay gcSay
				// gcSay.ObjectID = ai.Body.ObjectID
				// gcSay.setMessage(g_pStringPool.getString(parameter ));
				// gcSay.setColor(0x00ffffff);
				// ai.Body.getZone().broadcastPacket(ai.Body.getX(), ai.Body.getY(),
				// &gcSay);
			}

			// break
		}
	}

	switch ai.LastAction {
	case LAST_ACTION_NONE:
		ai.setDelay(currentTime)
	case LAST_ACTION_MOVE:
		ai.setDelay(currentTime)
	case LAST_ACTION_SKILL:
		ai.setAttackDelay(currentTime)
	}

	ai.LastAction = LAST_ACTION_NONE

	if (rand.Int() & 0x0000007F) > 64 { //%100 > 50)
		if ai.bDamaged {
			ai.bDamaged = false
			ai.Panic = ai.PanicMax
			ai.Courage = ai.CourageMax
		}
	}
}
예제 #18
0
파일: pcinfo.go 프로젝트: sguzwf/ouster
func (info *PCSlayerInfo) Read(reader io.Reader) error {
	binary.Read(reader, binary.LittleEndian, &info.ObjectID)
	var szName uint8
	var buf [256]byte
	binary.Read(reader, binary.LittleEndian, &szName)
	log.Debugln("szName=", szName)
	_, err := reader.Read(buf[:szName])
	if err != nil {
		return err
	}
	info.Name = string(buf[:szName])
	log.Debugln("sdkjfasdlgasjdfasdf", info.Name, szName)
	binary.Read(reader, binary.LittleEndian, &info.Sex)
	binary.Read(reader, binary.LittleEndian, &info.HairStyle)
	binary.Read(reader, binary.LittleEndian, &info.HairColor)
	binary.Read(reader, binary.LittleEndian, &info.SkinColor)
	binary.Read(reader, binary.LittleEndian, &info.MasterEffectColor)
	binary.Read(reader, binary.LittleEndian, &info.Alignment)
	binary.Read(reader, binary.LittleEndian, &info.STR[ATTR_CURRENT])
	binary.Read(reader, binary.LittleEndian, &info.STR[ATTR_MAX])
	binary.Read(reader, binary.LittleEndian, &info.STR[ATTR_BASIC])
	binary.Read(reader, binary.LittleEndian, &info.DEX[ATTR_CURRENT])
	binary.Read(reader, binary.LittleEndian, &info.DEX[ATTR_MAX])
	binary.Read(reader, binary.LittleEndian, &info.DEX[ATTR_BASIC])
	binary.Read(reader, binary.LittleEndian, &info.INI[ATTR_CURRENT])
	binary.Read(reader, binary.LittleEndian, &info.INI[ATTR_MAX])
	binary.Read(reader, binary.LittleEndian, &info.INI[ATTR_BASIC])

	binary.Read(reader, binary.LittleEndian, &info.Rank)
	binary.Read(reader, binary.LittleEndian, &info.RankExp)

	binary.Read(reader, binary.LittleEndian, &info.STRExp)
	binary.Read(reader, binary.LittleEndian, &info.DEXExp)
	binary.Read(reader, binary.LittleEndian, &info.INIExp)

	binary.Read(reader, binary.LittleEndian, &info.HP[ATTR_CURRENT])
	binary.Read(reader, binary.LittleEndian, &info.HP[ATTR_MAX])
	binary.Read(reader, binary.LittleEndian, &info.MP[ATTR_CURRENT])
	binary.Read(reader, binary.LittleEndian, &info.MP[ATTR_MAX])

	binary.Read(reader, binary.LittleEndian, &info.Fame)
	binary.Read(reader, binary.LittleEndian, &info.Gold)

	for i := 0; i < SKILL_DOMAIN_VAMPIRE; i++ {
		binary.Read(reader, binary.LittleEndian, &info.DomainLevels[i])
		binary.Read(reader, binary.LittleEndian, &info.DomainExps[i])
	}

	binary.Read(reader, binary.LittleEndian, &info.Sight)

	for i := 0; i < 4; i++ {
		binary.Read(reader, binary.LittleEndian, &info.HotKey[i])
	}

	binary.Read(reader, binary.LittleEndian, &info.Competence)
	binary.Read(reader, binary.LittleEndian, &info.GuildID)

	var szGuildName uint8
	_, err = reader.Read(buf[:szGuildName])
	if err != nil {
		return err
	}
	info.GuildName = string(buf[:szGuildName])

	binary.Read(reader, binary.LittleEndian, &info.GuildMemberRank)
	binary.Read(reader, binary.LittleEndian, &info.UnionID)
	binary.Read(reader, binary.LittleEndian, &info.AdvancementLevel)
	binary.Read(reader, binary.LittleEndian, &info.AdvancementGoalExp)
	binary.Read(reader, binary.LittleEndian, &info.AttrBonus)
	return nil
}
예제 #19
0
func (sharphail SharpHail) ExecuteToTile(skill *packet.CGSkillToTilePacket, agent *Agent) {
	// weapon := agent.getWearItem(OUSTER_WEAR_RIGHTHAND)
	// if weapon == nil || weapon.ItemClass() != ITEM_CLASS_OUSTERS_CHAKRAM {
	//     // TODO
	//     return
	// }

	if !sharphail.Check(skill.SkillType, agent) {
		// TODO
		return
	}

	pc := agent.PlayerCreatureInstance()
	// skillslot := pc.SkillSlot[skill.SkillType]

	var input SkillInput
	var output SkillOutput
	// input.SkillLevel = skillslot.Level
	// input.DomainLevel =
	input.STR = int(pc.STR[ATTR_CURRENT])
	input.DEX = int(pc.DEX[ATTR_CURRENT])
	input.INT = int(pc.INI[ATTR_CURRENT])

	sharphail.ComputeOutput(&input, &output)
	scene := pc.Scene

	for x := skill.X - 2; x < skill.X+2; x++ {
		for y := skill.Y - 2; y < skill.Y+2; y++ {
			if x < 0 || ZoneCoord_t(x) >= scene.Width || y < 0 || ZoneCoord_t(y) >= scene.Height {
				continue
			}

			tile := scene.Tile(int(x), int(y))
			if !tile.canAddEffect() {
				continue
			}

			var creatureItf CreatureInterface
			if tile.HasCreature(MOVE_MODE_WALKING) {
				creatureItf = tile.getCreature(MOVE_MODE_WALKING)
			} else {
				continue
			}

			damage := output.Damage
			damage += int(agent.computeDamage(creatureItf, false))

			effect := new(EffectSharpHail)
			effect.X = ZoneCoord_t(x)
			effect.Y = ZoneCoord_t(y)
			effect.Scene = scene

			effect.UserObjectID = pc.ObjectID
			log.Debugln("userObjectID ---", pc.ObjectID)
			// effect.Deadline = time.Now().Add(time.Duration(output.Duration) * time.Millisecond)
			// effect.NextTime = time.Now().Add(3 * time.Millisecond)

			effect.Deadline = time.Now().Add(time.Duration(output.Duration) * time.Second)
			effect.NextTime = time.Now().Add(3 * time.Millisecond)

			effect.Tick = output.Tick
			effect.Damage = damage / 3
			// effect.Level = skillslot.ExpLevel

			// TODO 加锁
			scene.registeObject(effect)
			scene.effectManager.addEffect(effect)
			tile.addEffect(effect)
		}
	}

	// ok1是回复攻击者技能施放成功
	agent.sendPacket(&packet.GCSkillToTileOK1{
		SkillType: skill.SkillType,
		CEffectID: skill.CEffectID,
		X:         skill.X,
		Y:         skill.Y,
		Duration:  Duration_t(output.Duration),
		Range:     5,
	})

	// ok5是发给即能看到施放者,又能看到tile的玩家
	ok5 := &packet.GCSkillToTileOK5{
		ObjectID:  pc.ObjectID,
		SkillType: skill.SkillType,
		X:         skill.X,
		Y:         skill.Y,
		Duration:  Duration_t(output.Duration),
	}

	scene.broadcastSkillPacket(pc.X, pc.Y, ZoneCoord_t(skill.X), ZoneCoord_t(skill.Y), ok5, agent)

	// ok3是向施法者周围广播施放成功
	scene.broadcastPacket(pc.X, pc.Y, &packet.GCSkillToTileOK3{
		ObjectID:  pc.ObjectID,
		SkillType: skill.SkillType,
		X:         skill.X,
		Y:         skill.Y,
	}, agent)

	// ok4是向tile周围广播
	scene.broadcastPacket(ZoneCoord_t(skill.X), ZoneCoord_t(skill.Y), &packet.GCSkillToTileOK4{
		SkillType: skill.SkillType,
		X:         Coord_t(skill.X),
		Y:         Coord_t(skill.Y),
		Duration:  uint16(output.Duration),
	}, agent)
}
예제 #20
0
// 注意:需要在agent的goroutine中执行的
func (melee AttackMelee) ExecuteToObject(sender CreatureInterface, target CreatureInterface) {
	rangeCheck := verifyDistance(sender, target)
	hitRoll := HitRoll(sender, target, 0)

	if rangeCheck && hitRoll {
		if agent, ok := sender.(*Agent); ok {
			damage := agent.computeDamage(target, false)
			// 这个伤害是要广播给地图周围玩家知道的
			agent.scene <- DamageMessage{
				Agent:    agent,
				target:   target,
				damage:   damage,
				critical: false,
			}

			// 发给攻击者,告诉他攻击成功了
			ok1 := packet.GCAttackMeleeOK1{
				ObjectID: target.CreatureInstance().ObjectID,
			}
			agent.sendPacket(ok1)

			if slayer, ok := agent.PlayerCreatureInterface.(*Slayer); ok {
				weapon := slayer.getWearItem(SLAYER_WEAR_RIGHTHAND)
				switch weapon.ItemClass() {
				case ITEM_CLASS_BLADE:
					// increaseDomainExp(slayer, SKILL_DOMAIN_BLADE, 1, packet.GCAttackMeleeOK1{}, targetCreature.CreatureInstance().Level)
				case ITEM_CLASS_SWORD:
					// increaseDomainExp(slayer, SKILL_DOMAIN_BLADE, 1, packet.GCAttackMeleeOK1{}, targetCreature.CreatureInstance().Level)
				case ITEM_CLASS_CROSS:
					// increaseDomainExp(slayer, SKILL_DOMAIN_BLADE, 1, packet.GCAttackMeleeOK1{}, targetCreature.CreatureInstance().Level)
				case ITEM_CLASS_MACE:
					// increaseDomainExp(slayer, SKILL_DOMAIN_BLADE, 1, packet.GCAttackMeleeOK1{}, targetCreature.CreatureInstance().Level)
				default:
					log.Errorln("武器不对!")
				}
			}
		}

		if monster, ok := sender.(*Monster); ok {
			damage := monster.computeDamage(target, false)
			if agent, ok := target.(*Agent); ok {
				pc := agent.PlayerCreatureInstance()
				if pc.HP[ATTR_CURRENT] < HP_t(damage) {
					// 玩家被打死了
					log.Debugln("玩家被打死还没实现")
				} else {
					pc.HP[ATTR_CURRENT] -= HP_t(damage)

					log.Debugln("怪物攻击玩家,广播状态信息的攻击成功")
					// 广播给所有玩家,攻击成功
					ok3 := packet.GCAttackMeleeOK3{
						ObjectID:       sender.CreatureInstance().ObjectID,
						TargetObjectID: target.CreatureInstance().ObjectID,
					}
					pc.Scene.broadcastPacket(pc.X, pc.Y, ok3, agent)

					// 广播给所有玩家,状态变化
					status := packet.GCStatusCurrentHP{
						ObjectID:  pc.ObjectID,
						CurrentHP: pc.HP[ATTR_CURRENT],
					}
					pc.Scene.broadcastPacket(pc.X, pc.Y, status, nil)
				}
			} else {
				log.Errorln("参数不对")
			}
		}

		switch agent := target.(type) {
		case *Agent:
			agent.sendPacket(packet.GCAttackMeleeOK2{
				ObjectID: sender.CreatureInstance().ObjectID,
			})
		case *Monster:
			// monster := target.(*Monster)
			// monster.addEnemy(agent)
		}
	}
}