Пример #1
0
func CGSkillToTileHandler(pkt packet.Packet, agent *Agent) {
	if agent.PlayerStatus != GPS_NORMAL {
		return
	}

	// 检查变身狼状态一些技能不可用

	// if slayer, ok := agent.PlayerCreature.(Ouster); ok {
	//
	// }

	skillPacket := pkt.(*packet.CGSkillToTilePacket)
	skillHandler, ok := skillTable[skillPacket.SkillType]
	if !ok {
		log.Errorln("尚未实现的skill", skillPacket.SkillType)
		return
	}

	handler, ok := skillHandler.(SkillToTileInterface)
	if !ok {
		log.Errorln(skillPacket.SkillType, "没有实现SkillToTile接口")
		return
	}

	handler.ExecuteToTile(skillPacket, agent)
}
Пример #2
0
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
			}
		}
	}()
}
Пример #3
0
func (agent *Agent) handleClientMessage(pkt packet.Packet) {
	if pkt == nil {
		log.Errorln("不应该呀 怎么可能返回一个空")
	}
	handler, ok := packetHandlers[pkt.PacketID()]
	if !ok {
		log.Errorln("packet的handler未实现:", pkt.PacketID())
		return
	}

	handler(pkt, agent)
}
Пример #4
0
func (vampire *Vampire) computeDamage(creature CreatureInterface, bCritical bool) Damage_t {
	minDamage := vampire.Damage[ATTR_CURRENT]
	maxDamage := vampire.Damage[ATTR_MAX]
	// timeband    := getZoneTimeband(vampire->getZone())
	// TODO
	timeband := 0
	// pItem := vampire.getWearItem(Vampire_WEAR_RIGHTHAND)
	//
	// if pItem != nil {
	//     MinDamage += pItem.getMinDamage()
	//     MaxDamage += pItem.getMaxDamage()
	// }

	realDamage := max(1, int(minDamage)+rand.Intn(int(maxDamage-minDamage)))
	realDamage = getPercentValue(realDamage, VampireTimebandFactor[timeband])

	var protection Protection_t
	switch creature.(type) {
	case *Vampire:
		protection = creature.(*Vampire).Protection[ATTR_CURRENT]
		protection = Protection_t(getPercentValue(int(protection), VampireTimebandFactor[timeband]))
	case *Monster:
		protection = creature.(*Monster).Protection
		protection = Protection_t(getPercentValue(int(protection), VampireTimebandFactor[timeband]))
	case *Slayer:
		protection = creature.(*Slayer).Protection[ATTR_CURRENT]
	case *Ouster:
		protection = creature.(*Ouster).Protection[ATTR_CURRENT]
	default:
		log.Errorln("输入的参数不对")
	}
	finalDamage := Damage_t(computeFinalDamage(minDamage, maxDamage, Damage_t(realDamage), protection, bCritical))

	return finalDamage
}
Пример #5
0
// 这个函数只能在scene的goroutine中调用
// 被攻击者是怪物,直接减血
// 被攻击者是玩家,发到agent的goroutine中去计算
func (m *Scene) setDamage(target CreatureInterface, agent *Agent, damage Damage_t) {
	var status packet.GCStatusCurrentHP
	switch target.(type) {
	case *Agent:
		// TODO
	case *Monster:
		monster := target.(*Monster)
		if monster.HP[ATTR_CURRENT] < HP_t(damage) {
			// 这里只是设置dead标志,在MonsterManager的heartbeat中kill
			monster.HP[ATTR_CURRENT] = 0
			monster.LastKiller = agent.ObjectInstance().ObjectID
		} else {
			monster.HP[ATTR_CURRENT] -= HP_t(damage)
			status = packet.GCStatusCurrentHP{
				ObjectID:  monster.ObjectID,
				CurrentHP: monster.HP[ATTR_CURRENT],
			}
		}
	default:
		log.Errorln("参数不对")
	}

	pc := agent.CreatureInstance()

	// // 广播给所有玩家,攻击成功,怪物状态变化
	// ok3 := packet.GCAttackMeleeOK3{
	//     ObjectID:       pc.ObjectID,
	//     TargetObjectID: target.CreatureInstance().ObjectID,
	// }
	// m.broadcastPacket(pc.X, pc.Y, ok3, agent)

	m.broadcastPacket(pc.X, pc.Y, status, nil)
}
Пример #6
0
func loadSlayer(decoder *json.Decoder) (slayer *Slayer, zoneID ZoneID_t, err error) {
	var pcInfo data.PCSlayerInfo
	err = decoder.Decode(&pcInfo)
	if err != nil {
		log.Errorln("decode pcinfo failed")
		return
	}

	slayer = new(Slayer)
	slayer.Init()
	slayer.Name = pcInfo.Name
	slayer.HairColor = pcInfo.HairColor
	slayer.MasterEffectColor = pcInfo.MasterEffectColor
	slayer.Alignment = pcInfo.Alignment
	slayer.STR = pcInfo.STR
	slayer.DEX = pcInfo.DEX
	slayer.INI = pcInfo.INI
	slayer.HP[ATTR_MAX] = pcInfo.HP[ATTR_MAX]
	slayer.HP[ATTR_CURRENT] = pcInfo.HP[ATTR_CURRENT]
	slayer.MP[ATTR_MAX] = pcInfo.MP[ATTR_MAX]
	slayer.MP[ATTR_CURRENT] = pcInfo.MP[ATTR_CURRENT]
	slayer.Rank = pcInfo.Rank
	slayer.RankExp = pcInfo.RankExp
	slayer.Fame = pcInfo.Fame
	slayer.Sight = pcInfo.Sight
	slayer.Competence = pcInfo.Competence
	slayer.GuildMemberRank = pcInfo.GuildMemberRank
	slayer.AdvancementLevel = pcInfo.AdvancementLevel

	for i := 0; i < 6; i++ {
		slayer.DomainLevels[i] = pcInfo.DomainLevels[i]
		slayer.DomainExps[i] = pcInfo.DomainExps[i]
	}

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

	// var skillInfo packet.OusterSkillInfo
	// err = decoder.Decode(&skillInfo)
	// if err != nil {
	//     return
	// }
	//
	// slayer.SkillSlot = make(map[SkillType_t]*OusterSkillSlot)
	// for _, v := range skillInfo.SubOusterSkillInfoList {
	//     skillslot := &OusterSkillSlot{
	//         // Name        string
	//         SkillType:   v.SkillType,
	//         ExpLevel:    v.ExpLevel,
	//         Interval:    time.Duration(v.Interval) * time.Millisecond,
	//         CastingTime: time.Duration(v.CastingTime) * time.Millisecond,
	//         // RunTime     time.Time
	//     }
	//     slayer.SkillSlot[v.SkillType] = skillslot
	// }

	return
}
Пример #7
0
func loadOuster(decoder *json.Decoder) (ouster *Ouster, zoneID ZoneID_t, err error) {
	var pcInfo data.PCOusterInfo
	err = decoder.Decode(&pcInfo)
	if err != nil {
		log.Errorln("decode pcinfo failed")
		return
	}

	ouster = new(Ouster)
	ouster.Init()
	ouster.Name = pcInfo.Name
	ouster.Level = pcInfo.Level
	ouster.HairColor = pcInfo.HairColor
	ouster.MasterEffectColor = pcInfo.MasterEffectColor
	ouster.Alignment = pcInfo.Alignment
	ouster.STR = pcInfo.STR
	ouster.DEX = pcInfo.DEX
	ouster.INI = pcInfo.INI
	ouster.HP[ATTR_MAX] = pcInfo.HP[ATTR_MAX]
	ouster.HP[ATTR_CURRENT] = pcInfo.HP[ATTR_CURRENT]
	ouster.MP[ATTR_MAX] = pcInfo.MP[ATTR_MAX]
	ouster.MP[ATTR_CURRENT] = pcInfo.MP[ATTR_CURRENT]
	ouster.Rank = pcInfo.Rank
	ouster.RankExp = pcInfo.RankExp
	ouster.Exp = pcInfo.Exp
	ouster.Fame = pcInfo.Fame
	ouster.Sight = pcInfo.Sight
	ouster.Bonus = pcInfo.Bonus
	ouster.Competence = pcInfo.Competence
	ouster.GuildMemberRank = pcInfo.GuildMemberRank
	ouster.AdvancementLevel = pcInfo.AdvancementLevel

	zoneID = pcInfo.ZoneID
	ouster.X = pcInfo.ZoneX
	ouster.Y = pcInfo.ZoneY

	var skillInfo data.OusterSkillInfo
	err = decoder.Decode(&skillInfo)
	if err != nil {
		return
	}

	ouster.SkillSlot = make(map[SkillType_t]*OusterSkillSlot)
	for _, v := range skillInfo.SubOusterSkillInfoList {
		skillslot := &OusterSkillSlot{
			// Name        string
			SkillType:   v.SkillType,
			ExpLevel:    v.ExpLevel,
			Interval:    time.Duration(v.Interval) * time.Millisecond,
			CastingTime: time.Duration(v.CastingTime) * time.Millisecond,
			// RunTime     time.Time
		}
		ouster.SkillSlot[v.SkillType] = skillslot
	}

	return
}
Пример #8
0
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
}
Пример #9
0
func CGSkillToObjectHandler(pkt packet.Packet, agent *Agent) {
	skillPacket := pkt.(*packet.CGSkillToObjectPacket)
	skillHandler, ok := skillTable[skillPacket.SkillType]
	if !ok {
		log.Errorln("尚未实现的skill", skillPacket.SkillType)
		return
	}

	handler, ok := skillHandler.(SkillToObjectInterface)
	if !ok {
		log.Errorln(skillPacket.SkillType, "没有实现SkillToObject接口")
		return
	}

	// type GCSkillFailed1Packet struct {
	//     SkillType SkillType_t
	//     Grade     uint8
	//     ModifyInfo
	// }
	//     fail := packet.GCSkillToTileFail{
	//         SkillType: SKILL_ATTACK_MELEE,
	//     }

	pc := agent.PlayerCreatureInstance()
	obj, ok := pc.Scene.objects[skillPacket.TargetObjectID]
	if !ok {
		// TODO 发送失败包
		// agent.sendPacket()
		return
	}
	target, ok := obj.(CreatureInterface)
	if !ok {
		log.Error("不能对非creature的东西放技能")
		return
	}
	handler.ExecuteToObject(agent, target)
}
Пример #10
0
func (ouster *Ouster) computeDamage(creature CreatureInterface, bCritical bool) Damage_t {
	minDamage := ouster.Damage[ATTR_CURRENT]
	maxDamage := ouster.Damage[ATTR_MAX]
	// timeband    := getZoneTimeband(pVampire->getZone())
	// TODO
	timeband := 0
	// TODO
	// pItem := ouster.getWearItem(OUSTER_WEAR_RIGHTHAND)
	//
	// if pItem != nil {
	//     MinDamage += pItem.getMinDamage()
	//     MaxDamage += pItem.getMaxDamage()
	// }
	//

	scope := int(maxDamage - minDamage)
	if scope < 1 {
		scope = 1
	}
	realDamage := max(1, int(minDamage)+rand.Intn(scope))

	var protection Protection_t
	if creature != nil {
	again:
		switch creature.(type) {
		case *Vampire:
			protection = creature.(*Vampire).Protection[ATTR_CURRENT]
			protection = Protection_t(getPercentValue(int(realDamage), VampireTimebandFactor[timeband]))
		case *Monster:
			protection = creature.(*Monster).Protection
			protection = Protection_t(getPercentValue(int(realDamage), VampireTimebandFactor[timeband]))
		case *Slayer:
			protection = creature.(*Slayer).Protection[ATTR_CURRENT]
		case *Ouster:
			protection = creature.(*Ouster).Protection[ATTR_CURRENT]
		case *Agent:
			creature = creature.(*Agent).PlayerCreatureInterface
			goto again
		default:
			log.Errorln("输入的参数不对")
		}
	}

	finalDamage := computeFinalDamage(minDamage, maxDamage, Damage_t(realDamage), protection, bCritical)

	return finalDamage
}
Пример #11
0
func main() {
	ln, err := net.Listen("tcp", config.LoginServerPort)
	if err != nil {
		panic(err)
	}
	log.Infoln("loginserver started")
	for {
		conn, err := ln.Accept()
		if err != nil {
			log.Errorln("accept err:", err)
			continue
		}

		log.Infoln("receive a connect request")
		go serve(conn)
	}
}
Пример #12
0
func (ai *MonsterAI) useSkill(pEnemy CreatureInterface, SkillType SkillType_t, ratio int) int {
	// enemy := pEnemy.CreatureInstance()
	// ex := enemy.X
	// ey := enemy.Y
	// dist := ai.Body.getDistance(ex, ey)

	if rand.Intn(100) >= ratio {
		// return SKILL_FAILED_RATIO
		return -1
	}

	if ai.Body.isFlag(EFFECT_CLASS_HIDE) {
		SkillType = SKILL_UN_BURROW
	} else if ai.Body.isFlag(EFFECT_CLASS_TRANSFORM_TO_BAT) {
		SkillType = SKILL_UN_TRANSFORM
	} else if ai.Body.isFlag(EFFECT_CLASS_INVISIBILITY) {
		SkillType = SKILL_UN_INVISIBILITY
	}

	skill, ok := skillTable[SkillType]
	if !ok {
		log.Errorf("技能%d的handler没有实现!!", SkillType)
		return 0
	}

	switch handler := skill.(type) {
	case SkillToObjectInterface:
		// 移动计算,以闭包形式发到agent的goroutine中运行
		if agent, ok := pEnemy.(*Agent); ok {
			closure := func() {
				handler.ExecuteToObject(ai.Body, pEnemy)
			}
			agent.computation <- closure
		} else {
			log.Errorln("怪物打怪物还没实现")
		}

		ai.LastAction = LAST_ACTION_SKILL
	default:
		log.Warnln("skill handler没有实现", SkillType)
	}

	return 0
}
Пример #13
0
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())
		}
	}
}
Пример #14
0
func (m *MonsterManager) findPosition(zone *Zone, monsterType MonsterType_t) (x ZoneCoord_t, y ZoneCoord_t) {
	info, ok := data.MonsterInfoTable[monsterType]
	if !ok {
		log.Error("不对,找不到monster信息")
		return
	}
	for i := 0; i < 300; i++ {
		pt := zone.getRandomMonsterRegenPosition()
		tile := zone.Tile(int(pt.X), int(pt.Y))

		if !tile.isBlocked(info.MoveMode) &&
			!tile.hasPortal() &&
			(*zone.Level(int(pt.X), int(pt.Y))&ZoneLevel_t(SAFE_ZONE)) == 0 {
			x = ZoneCoord_t(pt.X)
			y = ZoneCoord_t(pt.Y)
			return
		}
	}
	log.Errorln("地图中找不到可以放怪物的点了...不科学!")
	return
}
Пример #15
0
func CGReadyHandler(pkt packet.Packet, agent *Agent) {
	pc := agent.PlayerCreatureInstance()
	if agent.PlayerStatus != GPS_WAITING_FOR_CG_READY {

	}

	// scene := GetScene(pc.ZoneID)
	// scene.agent <- AgentMsg{}

	// var save chan<- AgentMsg
	// 地图切换
	if agent.ZoneID != 0 {
		// save = agent.send
	}

	agent.sendPacket(&packet.GCSetPositionPacket{
		X:   uint8(pc.X),
		Y:   uint8(pc.Y),
		Dir: uint8(pc.Dir),
	})

	var skillInfo packet.GCSkillInfoPacket
	switch agent.PlayerCreatureInterface.(type) {
	case *Vampire:
		skillInfo.PCType = packet.PC_VAMPIRE
	case *Ouster:
		skillInfo.PCType = packet.PC_OUSTER
	case *Slayer:
		skillInfo.PCType = packet.PC_SLAYER
	default:
		log.Errorln("不应该运行到这里")
	}
	// skillInfo.PCSkillInfoList = []packet.SkillInfo{
	// agent.SkillInfo(),
	// }
	// log.Debugf("发送技能信息%#v\n", skillInfo)
	// agent.sendPacket(&skillInfo)
	agent.PlayerStatus = GPS_NORMAL
}
Пример #16
0
func (tile *Tile) deleteCreature(id ObjectID_t) {
	var object ObjectInterface
	object, ok := tile.Objects[id]
	if !ok {
		log.Warnf("object not exist in tile! id=%d tile=%#v\n", id, tile)
		return
	}

	delete(tile.Objects, id)

	var creature *Creature
	switch raw := object.(type) {
	case *Agent:
		creature = raw.CreatureInstance()
	case *Monster:
		creature = raw.CreatureInstance()
	default:
		log.Errorln(raw)
		panic("不对")
	}
	tile.Flags &^= (1 << (TILE_WALKING_CREATURE + creature.MoveMode))
	tile.Flags &^= (1 << (TILE_GROUND_BLOCKED + creature.MoveMode))
}
Пример #17
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)
		}
	}
}
Пример #18
0
func HitRoll(pAttacker CreatureInterface, pDefender CreatureInterface, bonus int) bool {
	if pDefender.CreatureInstance().isFlag(EFFECT_CLASS_NO_DAMAGE) {
		return false
	}

	var (
		tohit   ToHit_t
		defense Defense_t
	)
	//TODO
	// timeband = pZone->getTimeband();
	timeband := 0

again1:
	switch pAttacker.(type) {
	case *Slayer:
		tohit = pAttacker.(*Slayer).ToHit[ATTR_CURRENT]
	case *Ouster:
		tohit = pAttacker.(*Ouster).ToHit[ATTR_CURRENT]
	case *Vampire:
		tohit = pAttacker.(*Vampire).ToHit[ATTR_CURRENT]
		tohit = ToHit_t(getPercentValue(int(tohit), VampireTimebandFactor[timeband]))
	case *Monster:
		tohit = pAttacker.(*Monster).ToHit
		tohit = ToHit_t(getPercentValue(int(tohit), VampireTimebandFactor[timeband]))
	case *Agent:
		pAttacker = pAttacker.(*Agent).PlayerCreatureInterface
		goto again1
	default:
		log.Errorln("参数不对")
	}

again2:
	switch pDefender.(type) {
	case *Slayer:
		defense = pDefender.(*Slayer).Defense[ATTR_CURRENT]
	case *Ouster:
		defense = pDefender.(*Ouster).Defense[ATTR_CURRENT]
	case *Vampire:
		defense = pDefender.(*Vampire).Defense[ATTR_CURRENT]
		defense = Defense_t(getPercentValue(int(defense), VampireTimebandFactor[timeband]))
	case *Monster:
		defense = pDefender.(*Monster).Defense
		defense = Defense_t(getPercentValue(int(defense), VampireTimebandFactor[timeband]))
	case *Agent:
		pDefender = pDefender.(*Agent).PlayerCreatureInterface
		goto again2
	}

	randValue := rand.Intn(100)
	var result int

	if int(tohit) >= int(defense) {
		result = min(90, int(int((float64(int(tohit)-int(defense))/1.5))+60)+bonus)
	} else {
		if _, ok := pAttacker.(*Monster); ok {
			result = max(10, (int)(60-int((float64(defense)-float64(tohit))/1.5)+bonus))
		} else {
			result = max(20, (int)(60-int((float64(defense)-float64(tohit))/1.5)+bonus))
		}
	}

	if randValue <= result {
		return true
	}

	return false
}
Пример #19
0
func CGAttackHandler(pkt packet.Packet, agent *Agent) {
	fail := packet.GCSkillFailed1Packet{
		SkillType: SKILL_ATTACK_MELEE,
	}
	if agent.PlayerStatus != GPS_NORMAL {
		agent.sendPacket(&fail)
		return
	}

	pc := agent.PlayerCreatureInstance()
	zoneLevel := pc.Scene.getZoneLevel(pc.X, pc.Y)
	if (zoneLevel&ZoneLevel_t(COMPLETE_SAFE_ZONE)) != 0 ||
		pc.isFlag(EFFECT_CLASS_PARALYZE) ||
		pc.isFlag(EFFECT_CLASS_CAUSE_CRITICAL_WOUNDS) ||
		pc.isFlag(EFFECT_CLASS_EXPLOSION_WATER) ||
		pc.isFlag(EFFECT_CLASS_COMA) {
		agent.sendPacket(&fail)
		return
	}

	attack := pkt.(*packet.CGAttackPacket)
	target, ok := pc.Scene.objects[attack.ObjectID]
	if !ok {
		agent.sendPacket(&fail)
		return
	}

	if target.ObjectClass() != OBJECT_CLASS_CREATURE {
		agent.sendPacket(&fail)
		return
	}
	targetCreature := target.(CreatureInterface)

	// ok3 := packet.GCAttackMeleeOK3{}

	// skillslot = agent.hasSkill(SKILL_ATTACK_MELEE)
	// timeCheck := verifyRunTime(skillslot)
	rangeCheck := verifyDistance(agent, targetCreature)
	hitRoll := HitRoll(agent.PlayerCreatureInterface, targetCreature, 0)

	if rangeCheck && hitRoll {
		damage := agent.PlayerCreatureInterface.computeDamage(targetCreature, false)

		// 这个伤害是要广播给地图周围玩家知道的
		agent.scene <- DamageMessage{
			Agent:    agent,
			target:   targetCreature,
			damage:   damage,
			critical: false,
		}

		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("武器不对!")
			}
		}

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

		// skillslot.setRunTime()
	} else {
		// 执行失败处理
	}

	// agent.setLastTarget(target.ObjectID)

	// if monster, ok := target.(*Monster); ok {
	//        hit := HitTest(player.ToHit, monster.Defense)
	//        if hit {
	//            player.send <- packet.GCAttackMeleeOK1{
	//								ObjectID: monster.Id(),
	//						}
	//
	//            damage := 1
	//            if player.Damage > monster.Protection {
	//                damage = int(player.Damage - monster.Protection)
	//            }
	//
	//            log.Println("send attack SkillOutput to scene..........")
	//            player.Scene.agent <- AgentMessage{
	//                Player: player,
	//                Msg: SkillOutput{
	//                    MonsterID: attack.ObjectID,
	//                    Damage:    damage,
	//                },
	//            }
	//        } else {
	//            player.send <- &packet.GCSkillFailed1Packet{}
	//        }
	//		}
}
Пример #20
0
func (info *GCUpdateInfoPacket) Write(buf io.Writer, code uint8) error {
	var PCType byte
	switch info.PCInfo.(type) {
	case *data.PCOusterInfo:
		PCType = 'O'
	case *data.PCSlayerInfo:
		PCType = 'S'
	case *data.PCVampireInfo:
		PCType = 'V'
	default:
		log.Errorln("unknown PCInfo in GCUpdateInfoPacket")
	}
	binary.Write(buf, binary.LittleEndian, PCType)
	info.PCInfo.Write(buf)
	info.InventoryInfo.Write(buf)
	info.GearInfo.Write(buf)
	info.ExtraInfo.Write(buf)
	info.EffectInfo.Write(buf)
	if info.hasMotorcycle {
		binary.Write(buf, binary.LittleEndian, uint8(1))
		info.RideMotorcycleInfo.Dump(buf)
	} else {
		binary.Write(buf, binary.LittleEndian, uint8(0))
	}

	binary.Write(buf, binary.LittleEndian, info.ZoneID)
	binary.Write(buf, binary.LittleEndian, info.ZoneX)
	binary.Write(buf, binary.LittleEndian, info.ZoneY)

	info.GameTime.Dump(buf)
	binary.Write(buf, binary.LittleEndian, info.Weather)
	binary.Write(buf, binary.LittleEndian, info.WeatherLevel)
	binary.Write(buf, binary.LittleEndian, info.DarkLevel)
	binary.Write(buf, binary.LittleEndian, info.LightLevel)

	binary.Write(buf, binary.LittleEndian, uint8(len(info.NPCTypes)))
	for i := 0; i < len(info.NPCTypes); i++ {
		binary.Write(buf, binary.LittleEndian, info.NPCTypes[i])
	}

	binary.Write(buf, binary.LittleEndian, uint8(len(info.MonsterTypes)))
	for i := 0; i < len(info.MonsterTypes); i++ {
		binary.Write(buf, binary.LittleEndian, info.MonsterTypes[i])
	}

	binary.Write(buf, binary.LittleEndian, uint8(len(info.NPCInfos)))
	for i := 0; i < len(info.NPCInfos); i++ {
		info.NPCInfos[i].Write(buf)
	}

	binary.Write(buf, binary.LittleEndian, info.ServerStat)
	binary.Write(buf, binary.LittleEndian, info.Premium)
	binary.Write(buf, binary.LittleEndian, info.SMSCharge)

	info.NicknameInfo.Write(buf)

	if info.NonPK {
		binary.Write(buf, binary.LittleEndian, uint8(1))
	} else {
		binary.Write(buf, binary.LittleEndian, uint8(0))
	}

	binary.Write(buf, binary.LittleEndian, info.GuildUnionID)
	binary.Write(buf, binary.LittleEndian, info.GuildUnionUserType)

	info.BloodBibleSignInfo.Write(buf)

	binary.Write(buf, binary.LittleEndian, info.PowerPoint)

	return nil

	// return

	// buf.Write([]byte{190, 7,
	// 	 3,
	// 	 19,
	// 	 16,
	// 	10,
	// 	40,
	//
	// 	0, Weather
	// 	0, WeatherLevel
	// 	13, DarkLevel
	// 	2, LightLevel
	//
	// 	0, nNPCS
	//
	// 	5, nMonsters
	// 	9, 0, monsterTypes
	// 	61, 0,
	// 	62, 0,
	// 	64, 0,
	// 	163, 0,
	//
	// 	0, NPCInfoCount
	// 	0, ServerStat
	// 	17, Premium
	// 	0, 0, 0, 0, SMSCharge
	// 	NickNameInfo
	// 	24, 125, 0,
	//
	// 	0, NonPK
	// 	0, 0, 0, 0, GuildUnionID
	// 	2, GuildUnionUserType
	// 	1, 0, 0, 0, 0,
	//  0, 0, 0, 0})	PowerPoint
	// return nil

	// return []byte{86, 117, 48, 0, 0, 4, 183, 232, 191, 241, 150, 0, 0, 0, 164, 1, 0, 76, 29, 0, 0,
	// 		20, 0, 20, 0, 20, 0, 20, 0, 20, 0, 20, 0, 20, 0, 20, 0, 20, 0, 216, 1, 216, 1, 50, 204, 41, 0, 0, 125, 0, 0,
	// 		0, 0, 0, 0, 0, 26, 1, 0, 0, 13, 15, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 4, 0, 0,
	// 		0, 0, 100, 0, 0, 0, 0, 6, 118, 48, 0, 0, 30, 0, 0, 0, 232, 3, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 119,
	// 		48, 0, 0, 44, 0, 0, 2, 16, 1, 136, 19, 0, 0, 0, 0, 3, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 120, 48, 0, 0, 34, 5, 0, 0,
	// 		1, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0, 8, 0, 0, 0, 0, 1, 121, 48, 0, 0, 32, 0, 0, 2, 53, 43, 232, 3, 0, 0,
	// 		0, 0, 4, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 122, 48, 0, 0, 32, 1, 0, 0, 232, 3, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 3, 123, 48, 0,
	// 		0, 44, 0, 0, 2, 58, 38, 32, 28, 0, 0, 0, 0, 4, 0, 0, 0, 0, 1, 0, 0, 0, 0, 4, 0, 0, 2, 146, 1, 54, 66, 109, 0, 246, 224, 0, 21, 0, 145, 237, 190, 7, 3, 19, 16,
	// 		10, 40, 0, 0, 13, 2, 0, 5, 9, 0, 61, 0, 62, 0, 64, 0, 163, 0, 0, 0, 17, 0, 0, 0, 0, 24, 125, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0},
	// 	nil
}
Пример #21
0
func CGConnectHandler(pkt packet.Packet, agent *Agent) {
	raw := pkt.(*packet.CGConnectPacket)
	pcItf, zid, err := LoadPlayerCreature(raw.PCName, packet.PCType(raw.PCType))
	if err != nil {
		log.Errorln("LoadPlayerCreature失败了:", err)
	}

	agent.PlayerCreatureInterface = pcItf
	scene, ok := g_Scenes[zid]
	if !ok {
		log.Errorln("加载的agent所在的scene不存在:", zid)
		agent.ErrorClose()
		return
	}
	agent.scene = scene.agent
	msg := LoginMessage{
		Agent: agent,
		wg:    &sync.WaitGroup{},
	}
	// 向scene发消息并等待其返回
	msg.wg.Add(1)
	agent.scene <- msg
	msg.wg.Wait()

	// log.Debugln("坐标:", agent.CreatureInstance().X,
	// agent.CreatureInstance().Y)
	info := &packet.GCUpdateInfoPacket{
		PCInfo: agent.PCInfo(),
		ZoneID: zid,
		ZoneX:  Coord_t(agent.CreatureInstance().X),
		ZoneY:  Coord_t(agent.CreatureInstance().Y),

		GameTime: packet.GameTimeType{
			Year:  1983,
			Month: 8,
			Day:   19,

			Hour:   12,
			Minute: 28,
			Second: 16,
		},

		DarkLevel:  13,
		LightLevel: 6,

		MonsterTypes: []MonsterType_t{5, 6, 7, 8},

		Premium: 17,
		NicknameInfo: data.NicknameInfo{
			NicknameID: 32560,
		},

		GuildUnionUserType: 2,
	}

	code := Encrypt(uint16(agent.CreatureInstance().Scene.ZoneID), 1)
	agent.packetReader.Code = code
	agent.packetWriter.Code = code

	if _, ok := info.PCInfo.(*data.PCOusterInfo); ok {
		info.GearInfo = data.GearInfo{
			GearSlotInfoList: []data.GearSlotInfo{
				data.GearSlotInfo{
					PCItemInfo: data.PCItemInfo{
						ObjectID:   12494,
						IClass:     59,
						ItemType:   14,
						Durability: 6700,
						Grade:      4,
						ItemNum:    1,
					},
					SlotID: 3,
				},
			},
		}
	}

	agent.sendPacket(info)
	agent.sendPacket(&packet.GCPetInfoPacket{})
	agent.PlayerStatus = GPS_WAITING_FOR_CG_READY
}