테스트

aion-server 4.8

Gitteol
최고관리자 · 1 · 💬 0 클론/새로받기
 4.8 61f661d · 1 commits 새로받기(Pull)
game-server/src/com/aionemu/gameserver/spawnengine/WalkerGroup.java
package com.aionemu.gameserver.spawnengine;

import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.aionemu.gameserver.ai.AILogger;
import com.aionemu.gameserver.ai.AIState;
import com.aionemu.gameserver.ai.AISubState;
import com.aionemu.gameserver.ai.NpcAI;
import com.aionemu.gameserver.ai.manager.WalkManager;
import com.aionemu.gameserver.model.gameobjects.Npc;
import com.aionemu.gameserver.model.templates.spawns.SpawnTemplate;
import com.aionemu.gameserver.model.templates.walker.RouteStep;
import com.aionemu.gameserver.model.templates.zone.Point2D;

/**
 * @author vlog, Rolandas
 */
public class WalkerGroup {

	private static final Logger log = LoggerFactory.getLogger(WalkerGroup.class);

	private List<ClusteredNpc> members;
	private WalkerGroupType type;
	private final float walkerXpos;
	private final float walkerYpos;
	private int[] memberSteps;
	private volatile int groupStep;
	private final String versionId;
	private boolean isSpawned;

	public WalkerGroup(List<ClusteredNpc> members) {
		this.members = members.stream().sorted(Comparator.comparing(ClusteredNpc::getWalkerIndex, Comparator.nullsLast(Comparator.naturalOrder())))
			.collect(Collectors.toList());
		memberSteps = new int[members.size()];
		walkerXpos = members.get(0).getX();
		walkerYpos = members.get(0).getY();
		type = members.get(0).getWalkTemplate().getType();
		versionId = members.get(0).getWalkTemplate().getVersionId();
	}

	public void form() {
		if (getWalkType() == WalkerGroupType.SQUARE) {
			int[] rows = members.get(0).getWalkTemplate().getRows();
			if (IntStream.of(rows).sum() != members.size()) {
				log.warn("Invalid row sizes for walk cluster " + members.get(0).getWalkTemplate().getRouteId());
			}
			if (rows.length == 1) {
				// Line formation: distance 2 meters from each other (divide by 2 and multiple by 2)
				// negative at left hand and positive at the right hand
				float bounds = (float) members.stream().mapToDouble(cNpc -> cNpc.getNpc().getObjectTemplate().getBoundRadius().getSide()).sum();
				float distance = (1 - members.size()) / 2f * (WalkerGroupShift.DISTANCE + bounds);
				Point2D origin = new Point2D(walkerXpos, walkerYpos);
				Point2D destination = new Point2D(members.get(0).getWalkTemplate().getRouteStep(1).getX(),
					members.get(0).getWalkTemplate().getRouteStep(1).getY());
				for (int i = 0; i < members.size(); i++, distance += WalkerGroupShift.DISTANCE) {
					WalkerGroupShift shift = new WalkerGroupShift(distance, 0);
					Point2D loc = getLinePoint(origin, destination, shift);
					members.get(i).setX(loc.getX());
					members.get(i).setY(loc.getY());
					Npc member = members.get(i).getNpc();
					member.setWalkerGroup(this);
					member.setWalkerGroupShift(shift);
					// distance += npc.getObjectTemplate().getBoundRadius().getSide();
				}
			} else if (rows.length != 0) {
				float rowDistances[] = new float[rows.length - 1];
				float coronalDist = 0;
				for (int i = 0; i < rows.length - 1; i++) {
					if (rows[i] % 2 != rows[i + 1] % 2)
						rowDistances[i] = 0.86602540378443864676372317075294f * WalkerGroupShift.DISTANCE;
					else
						rowDistances[i] = WalkerGroupShift.DISTANCE;
					coronalDist -= rowDistances[i];
				}
				Point2D origin = new Point2D(walkerXpos, walkerYpos);
				Point2D destination = new Point2D(members.get(0).getWalkTemplate().getRouteStep(1).getX(),
					members.get(0).getWalkTemplate().getRouteStep(1).getY());
				int index = 0;
				for (int i = 0; i < rows.length; i++) {
					float sagittalDist = (1 - rows[i]) / 2f * WalkerGroupShift.DISTANCE;
					for (int j = 0; j < rows[i]; j++, sagittalDist += WalkerGroupShift.DISTANCE) {
						if (index > members.size() - 1)
							break;
						WalkerGroupShift shift = new WalkerGroupShift(sagittalDist, coronalDist);
						Point2D loc = getLinePoint(origin, destination, shift);
						ClusteredNpc cnpc = members.get(index++);
						cnpc.setX(loc.getX());
						cnpc.setY(loc.getY());
						cnpc.getNpc().setWalkerGroup(this);
						cnpc.getNpc().setWalkerGroupShift(shift);
					}
					if (i < rows.length - 1)
						coronalDist += rowDistances[i];
				}
			}
		} else if (getWalkType() == WalkerGroupType.CIRCLE) {
			// TODO: if needed
		} else if (getWalkType() == WalkerGroupType.POINT) {
			log.warn("No formation specified for walk cluster " + members.get(0).getWalkTemplate().getRouteId());
		}
	}

	@SuppressWarnings("unused")
	private float getSidesExtra(int[] rows, int startIndex, int endIndex) {
		return 0;
	}

	/**
	 * Returns coordinates of NPC in 2D from the initial spawn location
	 * 
	 * @param origin
	 *          - initial spawn location
	 * @param destination
	 *          - point of next move
	 * @param shift
	 *          - distance from origin located in lines perpendicular to destination; for SagittalShift if negative then located to the left from
	 *          origin, otherwise, to the right for CoronalShift if negative then located to back, otherwise to the front
	 */
	public static Point2D getLinePoint(Point2D origin, Point2D destination, WalkerGroupShift shift) {
		// TODO: implement angle shift
		WalkerGroupShift dir = getShiftSigns(origin, destination);
		Point2D result = null;
		if (origin.getY() - destination.getY() == 0) {
			return new Point2D(origin.getX() + dir.getCoronalShift() * shift.getCoronalShift(),
				origin.getY() - dir.getSagittalShift() * shift.getSagittalShift());
		} else if (origin.getX() - destination.getX() == 0) {
			return new Point2D(origin.getX() + dir.getCoronalShift() * shift.getSagittalShift(),
				origin.getY() + dir.getCoronalShift() * shift.getCoronalShift());
		} else {
			double slope = (origin.getX() - destination.getX()) / (origin.getY() - destination.getY());
			double dx = Math.abs(shift.getSagittalShift()) / Math.sqrt(1 + slope * slope);
			if (shift.getSagittalShift() * dir.getCoronalShift() < 0)
				result = new Point2D((float) (origin.getX() - dx), (float) (origin.getY() + dx * slope));
			else
				result = new Point2D((float) (origin.getX() + dx), (float) (origin.getY() - dx * slope));
		}
		if (shift.getCoronalShift() != 0) {
			Point2D rotatedShift = null;
			if (shift.getSagittalShift() != 0) {
				rotatedShift = getLinePoint(origin, destination,
					new WalkerGroupShift(Math.signum(shift.getSagittalShift()) * Math.abs(shift.getCoronalShift()), 0));
			} else {
				rotatedShift = getLinePoint(origin, destination, new WalkerGroupShift(Math.abs(shift.getCoronalShift()), 0));
			}

			// since it's rotated, and perpendicular, dx and dy are reciprocal when not rotated
			float dx = Math.abs(origin.getX() - rotatedShift.getX());
			float dy = Math.abs(origin.getY() - rotatedShift.getY());
			if (shift.getCoronalShift() < 0) {
				if (dir.getSagittalShift() < 0 && dir.getCoronalShift() < 0) {
					result = new Point2D(result.getX() + dy, result.getY() + dx);
				} else if (dir.getSagittalShift() > 0 && dir.getCoronalShift() > 0) {
					result = new Point2D(result.getX() - dy, result.getY() - dx);
				} else if (dir.getSagittalShift() < 0 && dir.getCoronalShift() > 0) {
					result = new Point2D(result.getX() + dy, result.getY() - dx);
				} else if (dir.getSagittalShift() > 0 && dir.getCoronalShift() < 0) {
					result = new Point2D(result.getX() - dy, result.getY() + dx);
				}
			} else {
				if (dir.getSagittalShift() < 0 && dir.getCoronalShift() < 0) {
					result = new Point2D(result.getX() - dy, result.getY() - dx);
				} else if (dir.getSagittalShift() > 0 && dir.getCoronalShift() > 0) {
					result = new Point2D(result.getX() + dy, result.getY() + dx);
				} else if (dir.getSagittalShift() < 0 && dir.getCoronalShift() > 0) {
					result = new Point2D(result.getX() - dy, result.getY() + dx);
				} else if (dir.getSagittalShift() > 0 && dir.getCoronalShift() < 0) {
					result = new Point2D(result.getX() + dy, result.getY() - dx);
				}
			}
		}
		return result;
	}

	/*
	 * Return a normalized direction vector
	 */
	private static WalkerGroupShift getShiftSigns(Point2D origin, Point2D destination) {
		float dx = Math.signum(destination.getX() - origin.getX());
		float dy = Math.signum(destination.getY() - origin.getY());
		return new WalkerGroupShift(dx, dy);
	}

	public void setStep(Npc member, int step) {
		int currentStep = 0;
		for (int i = 0; i < members.size(); i++) {
			if (memberSteps[i] > currentStep)
				currentStep = memberSteps[i];
			if (members.get(i).getNpc().equals(member)) {
				AILogger.info(members.get(i).getNpc().getAi(), "Setting step to " + step);
				memberSteps[i] = step;
			}
		}
		if (step > currentStep || step == 0)
			groupStep = step;
	}

	public void targetReached(NpcAI npcAI) {
		synchronized (members) {
			npcAI.setSubStateIfNot(AISubState.WALK_WAIT_GROUP);
			boolean allArrived = true;
			for (ClusteredNpc snpc : members) {
				Npc npc = snpc.getNpc();
				allArrived &= npc.isDead() || npc.getAi().getSubState() == AISubState.WALK_WAIT_GROUP;
				if (!allArrived)
					break;
			}

			for (int i = 0; i < members.size(); i++) {
				ClusteredNpc snpc = members.get(i);
				if ((memberSteps[i] == groupStep) && !allArrived) {
					npcAI.getOwner().getMoveController().abortMove();
					npcAI.setStateIfNot(AIState.WALKING);
					npcAI.setSubStateIfNot(AISubState.WALK_WAIT_GROUP);
					continue;
				}
				npcAI = (NpcAI) (snpc.getNpc().getAi());
				if (npcAI.getSubState() == AISubState.WALK_WAIT_GROUP)
					WalkManager.targetReached(npcAI);
			}
		}
	}

	public boolean isSpawned() {
		return isSpawned;
	}

	public void spawn() {
		for (ClusteredNpc snpc : members) {
			float height = getHeight(snpc.getX(), snpc.getY(), snpc.getNpc().getSpawn());
			snpc.spawn(height);
		}
		isSpawned = true;
	}

	public void respawn(Npc npc) {
		for (int index = 0; index < members.size(); index++) {
			ClusteredNpc snpc = members.get(index);
			if (snpc.getNpc().getNpcId() == npc.getNpcId() && (npc.getSpawn().getWalkerIndex() == null && snpc.getNpc().isDead()
				|| npc.getSpawn().getWalkerIndex() != null && npc.getSpawn().getWalkerIndex() == snpc.getWalkerIndex())) {
				synchronized (members) {
					memberSteps[index] = Math.max(0, groupStep - 1);
					RouteStep step = snpc.getWalkTemplate().getRouteStep(memberSteps[index]);
					npc.getMoveController().setWalkerTemplate(snpc.getWalkTemplate(), memberSteps[index]);
					snpc.setNpc(npc, step);
					snpc.spawn(step.getZ());
				}
				break;
			}
		}
	}

	public void despawn() {
		for (ClusteredNpc snpc : members) {
			snpc.despawn();
			// reset positions
			form();
			for (int index = 0; index < memberSteps.length; index++)
				memberSteps[index] = 0;
			groupStep = 0;
		}
		isSpawned = false;
	}

	public ClusteredNpc getClusterData(Npc npc) {
		for (ClusteredNpc snpc : members) {
			if (snpc.getNpc().equals(npc))
				return snpc;
		}
		return null;
	}

	private float getHeight(float x, float y, SpawnTemplate template) {
		/*
		 * if (GeoService.getInstance().isGeoOn()) { return GeoService.getInstance().getZ(template.getWorldId(), x, y, z, ); }
		 */
		return template.getZ();
	}

	public int getPool() {
		return members.size();
	}

	public WalkerGroupType getWalkType() {
		return type;
	}

	public boolean isLinearlyPositioned(Npc npc) {
		if (type != WalkerGroupType.SQUARE)
			return false;
		for (ClusteredNpc snpc : members) {
			if (snpc.getNpc().equals(npc))
				return snpc.getWalkTemplate().getRows().length == 1;
		}
		return false;
	}

	public int getGroupStep() {
		return groupStep;
	}

	public String getVersionId() {
		return versionId;
	}

}

📎 첨부파일

댓글 작성 권한이 없습니다.
🏆 포인트 랭킹 TOP 10
순위 닉네임 포인트
1 no_profile 타키야겐지쪽지보내기 자기소개 아이디로 검색 전체게시물 102,949
2 no_profile 동가리쪽지보내기 자기소개 아이디로 검색 전체게시물 63,733
3 no_profile 라프텔쪽지보내기 자기소개 아이디로 검색 전체게시물 51,771
4 no_profile 불멸의행복쪽지보내기 자기소개 아이디로 검색 전체게시물 36,923
5 서번트쪽지보내기 자기소개 아이디로 검색 전체게시물 35,011
6 no_profile 닥터스쪽지보내기 자기소개 아이디로 검색 전체게시물 29,470
7 no_profile 검은고양이쪽지보내기 자기소개 아이디로 검색 전체게시물 29,077
8 no_profile Revolution쪽지보내기 자기소개 아이디로 검색 전체게시물 28,199
9 no_profile 보거스쪽지보내기 자기소개 아이디로 검색 전체게시물 26,731
10 no_profile 호롤롤로쪽지보내기 자기소개 아이디로 검색 전체게시물 17,020
알림 0