Added PlayerSystem and Map.Zone tracking

Created ZoneAwareComponent and ZoneUpdate tags
Added factory method to create players within Engine
This commit is contained in:
Collin Smith 2019-11-12 19:40:22 -08:00
parent 7c1c64823b
commit 3317794cb5
6 changed files with 388 additions and 0 deletions

View File

@ -8,6 +8,7 @@ import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.utils.Align; import com.badlogic.gdx.utils.Align;
import com.badlogic.gdx.utils.IntIntMap; import com.badlogic.gdx.utils.IntIntMap;
import com.riiablo.CharData;
import com.riiablo.Riiablo; import com.riiablo.Riiablo;
import com.riiablo.codec.COF; import com.riiablo.codec.COF;
import com.riiablo.codec.excel.Levels; import com.riiablo.codec.excel.Levels;
@ -16,6 +17,7 @@ import com.riiablo.codec.excel.MonStats;
import com.riiablo.codec.excel.MonStats2; import com.riiablo.codec.excel.MonStats2;
import com.riiablo.codec.excel.Objects; import com.riiablo.codec.excel.Objects;
import com.riiablo.codec.util.BBox; import com.riiablo.codec.util.BBox;
import com.riiablo.engine.component.AngleComponent;
import com.riiablo.engine.component.AnimationComponent; import com.riiablo.engine.component.AnimationComponent;
import com.riiablo.engine.component.BBoxComponent; import com.riiablo.engine.component.BBoxComponent;
import com.riiablo.engine.component.ClassnameComponent; import com.riiablo.engine.component.ClassnameComponent;
@ -25,11 +27,15 @@ import com.riiablo.engine.component.IdComponent;
import com.riiablo.engine.component.LabelComponent; import com.riiablo.engine.component.LabelComponent;
import com.riiablo.engine.component.MapComponent; import com.riiablo.engine.component.MapComponent;
import com.riiablo.engine.component.MonsterComponent; import com.riiablo.engine.component.MonsterComponent;
import com.riiablo.engine.component.MovementModeComponent;
import com.riiablo.engine.component.ObjectComponent; import com.riiablo.engine.component.ObjectComponent;
import com.riiablo.engine.component.PathComponent; import com.riiablo.engine.component.PathComponent;
import com.riiablo.engine.component.PlayerComponent;
import com.riiablo.engine.component.PositionComponent; import com.riiablo.engine.component.PositionComponent;
import com.riiablo.engine.component.TypeComponent; import com.riiablo.engine.component.TypeComponent;
import com.riiablo.engine.component.VelocityComponent;
import com.riiablo.engine.component.WarpComponent; import com.riiablo.engine.component.WarpComponent;
import com.riiablo.engine.component.ZoneAwareComponent;
import com.riiablo.map.DS1; import com.riiablo.map.DS1;
import com.riiablo.map.DT1; import com.riiablo.map.DT1;
import com.riiablo.map.Map; import com.riiablo.map.Map;
@ -78,6 +84,29 @@ public class Engine extends PooledEngine {
public static final byte MODE_RN = 15; public static final byte MODE_RN = 15;
} }
public static final class Player {
public static final byte MODE_DT = 0;
public static final byte MODE_NU = 1;
public static final byte MODE_WL = 2;
public static final byte MODE_RN = 3;
public static final byte MODE_GH = 4;
public static final byte MODE_TN = 5;
public static final byte MODE_TW = 6;
public static final byte MODE_A1 = 7;
public static final byte MODE_A2 = 8;
public static final byte MODE_BL = 9;
public static final byte MODE_SC = 10;
public static final byte MODE_TH = 11;
public static final byte MODE_KK = 12;
public static final byte MODE_S1 = 13;
public static final byte MODE_S2 = 14;
public static final byte MODE_S3 = 15;
public static final byte MODE_S4 = 16;
public static final byte MODE_DD = 17;
//public static final byte MODE_GH = 18;
//public static final byte MODE_GH = 19;
}
private static Label createLabel(String text) { private static Label createLabel(String text) {
Label label = new Label(Riiablo.fonts.font16); Label label = new Label(Riiablo.fonts.font16);
label.setAlignment(Align.center); label.setAlignment(Align.center);
@ -361,6 +390,57 @@ public class Engine extends PooledEngine {
return entity; return entity;
} }
public Entity createPlayer(Map map, Map.Zone zone, CharData charData, float x, float y) {
TypeComponent typeComponent = createComponent(TypeComponent.class);
typeComponent.type = TypeComponent.Type.PLR;
PlayerComponent playerComponent = createComponent(PlayerComponent.class);
playerComponent.charData = charData;
CofComponent cofComponent = createComponent(CofComponent.class);
cofComponent.mode = Player.MODE_TN;
AnimationComponent animationComponent = createComponent(AnimationComponent.class);
BBoxComponent boxComponent = createComponent(BBoxComponent.class);
boxComponent.box = animationComponent.animation.getBox();
PositionComponent positionComponent = createComponent(PositionComponent.class);
positionComponent.position.set(x, y);
VelocityComponent velocityComponent = createComponent(VelocityComponent.class);
velocityComponent.walkSpeed = 6;
velocityComponent.runSpeed = 9;
MovementModeComponent movementModeComponent = createComponent(MovementModeComponent.class);
movementModeComponent.NU = Player.MODE_TN;
movementModeComponent.WL = Player.MODE_TW;
movementModeComponent.RN = Player.MODE_RN;
ZoneAwareComponent zoneAwareComponent = createComponent(ZoneAwareComponent.class);
AngleComponent angleComponent = createComponent(AngleComponent.class);
MapComponent mapComponent = createComponent(MapComponent.class);
mapComponent.map = map;
mapComponent.zone = zone;
Entity entity = createEntity("player");
entity.add(typeComponent);
entity.add(cofComponent);
entity.add(animationComponent);
entity.add(boxComponent);
entity.add(positionComponent);
entity.add(velocityComponent);
entity.add(movementModeComponent);
entity.add(angleComponent);
entity.add(mapComponent);
entity.add(playerComponent);
entity.add(zoneAwareComponent);
return entity;
}
public static <T extends Component> T getOrCreateComponent(Entity entity, com.badlogic.ashley.core.Engine engine, Class<T> componentType, ComponentMapper<T> componentMapper) { public static <T extends Component> T getOrCreateComponent(Entity entity, com.badlogic.ashley.core.Engine engine, Class<T> componentType, ComponentMapper<T> componentMapper) {
T instance = componentMapper.get(entity); T instance = componentMapper.get(entity);
if (instance == null) entity.add(instance = engine.createComponent(componentType)); if (instance == null) entity.add(instance = engine.createComponent(componentType));

View File

@ -0,0 +1,8 @@
package com.riiablo.engine.component;
import com.badlogic.ashley.core.Component;
import com.badlogic.gdx.utils.Pool;
public class ZoneAwareComponent implements Component, Pool.Poolable {
@Override public void reset() {}
}

View File

@ -0,0 +1,8 @@
package com.riiablo.engine.component;
import com.badlogic.ashley.core.Component;
import com.badlogic.gdx.utils.Pool;
public class ZoneUpdate implements Component, Pool.Poolable {
@Override public void reset() {}
}

View File

@ -0,0 +1,217 @@
package com.riiablo.engine.system;
import com.badlogic.ashley.core.ComponentMapper;
import com.badlogic.ashley.core.Engine;
import com.badlogic.ashley.core.Entity;
import com.badlogic.ashley.core.EntityListener;
import com.badlogic.ashley.core.EntitySystem;
import com.badlogic.ashley.core.Family;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.ObjectMap;
import com.riiablo.CharData;
import com.riiablo.Riiablo;
import com.riiablo.codec.COF;
import com.riiablo.codec.excel.Armor;
import com.riiablo.codec.excel.Weapons;
import com.riiablo.engine.component.CofComponent;
import com.riiablo.engine.component.PlayerComponent;
import com.riiablo.engine.component.TypeComponent;
import com.riiablo.engine.component.cof.AlphaUpdate;
import com.riiablo.engine.component.cof.TransformUpdate;
import com.riiablo.item.BodyLoc;
import com.riiablo.item.Item;
import org.apache.commons.lang3.ObjectUtils;
public class PlayerSystem extends EntitySystem implements EntityListener, CharData.EquippedListener {
private static final String TAG = "PlayerSystem";
private static final boolean DEBUG = true;
private static final boolean DEBUG_STATE = DEBUG && !true;
private static final String[] TOKENS = {"AM", "SO", "NE", "PA", "BA", "DZ", "AI"};
private final ComponentMapper<PlayerComponent> charDataComponent = ComponentMapper.getFor(PlayerComponent.class);
private final ComponentMapper<CofComponent> cofComponent = ComponentMapper.getFor(CofComponent.class);
private final Family family = Family.all(PlayerComponent.class, CofComponent.class).get();
private final ComponentMapper<TransformUpdate> transformUpdate = ComponentMapper.getFor(TransformUpdate.class);
private final ComponentMapper<AlphaUpdate> alphaUpdate = ComponentMapper.getFor(AlphaUpdate.class);
private final ObjectMap<CharData, Entity> charDatas = new ObjectMap<>();
public PlayerSystem() {
setProcessing(false);
}
@Override
public void addedToEngine(Engine engine) {
super.addedToEngine(engine);
engine.addEntityListener(family, this);
}
@Override
public void removedFromEngine(Engine engine) {
super.removedFromEngine(engine);
engine.removeEntityListener(this);
}
@Override
public void entityAdded(Entity entity) {
PlayerComponent playerComponent = this.charDataComponent.get(entity);
CharData charData = playerComponent.charData;
loadItems(charData.getD2S().items.items);
CofComponent cofComponent = this.cofComponent.get(entity);
cofComponent.token = TOKENS[charData.getD2S().header.charClass];
updateWeaponClass(entity, charData, cofComponent);
updateArmorClass(entity, charData, cofComponent);
charDatas.put(charData, entity);
charData.addEquippedListener(this);
}
@Override
public void entityRemoved(Entity entity) {
}
private void loadItems(Array<Item> items) {
for (Item item : items) {
//item.setOwner(this);
item.load();
}
}
private void updateWeaponClass(Entity entity, CharData charData, CofComponent cof) {
Item RH = null, LH = null, SH = null;
Item rArm = charData.getEquipped2(BodyLoc.RARM);
if (rArm != null) {
if (rArm.type.is(com.riiablo.item.Type.WEAP)) {
RH = rArm;
} else if (rArm.type.is(com.riiablo.item.Type.SHLD)) {
SH = rArm;
}
}
Item lArm = charData.getEquipped2(BodyLoc.LARM);
if (lArm != null) {
if (lArm.type.is(com.riiablo.item.Type.WEAP)) {
LH = lArm;
} else if (lArm.type.is(com.riiablo.item.Type.SHLD)) {
SH = lArm;
}
}
if (DEBUG_STATE) {
Gdx.app.debug(TAG, "RH = " + RH);
Gdx.app.debug(TAG, "LH = " + LH);
Gdx.app.debug(TAG, "SH = " + SH);
}
if (LH != null && RH != null) {
Weapons.Entry LHEntry = LH.getBase();
Weapons.Entry RHEntry = RH.getBase();
if ( LHEntry.wclass.equals("1hs") && RHEntry.wclass.equals("1hs")) {
cof.wclass = CofComponent.WEAPON_1SS; // Left Swing Right Swing
} else if (LHEntry.wclass.equals("1hs") && RHEntry.wclass.equals("1ht")) {
cof.wclass = CofComponent.WEAPON_1ST; // Left Swing Right Thrust
} else if (LHEntry.wclass.equals("1ht") && RHEntry.wclass.equals("1hs")) {
cof.wclass = CofComponent.WEAPON_1JS; // Left Jab Right Swing
} else if (LHEntry.wclass.equals("1ht") && RHEntry.wclass.equals("1ht")) {
cof.wclass = CofComponent.WEAPON_1JT; // Left Jab Right Thrust
} else if (LH.type.is(com.riiablo.item.Type.MISS) || RH.type.is(com.riiablo.item.Type.MISS)) {
cof.wclass = Riiablo.files.WeaponClass.index(LH.type.is(com.riiablo.item.Type.MISS) ? LHEntry.wclass : RHEntry.wclass);
} else if (LH.type.is(com.riiablo.item.Type.H2H) || RH.type.is(com.riiablo.item.Type.H2H)) {
cof.wclass = CofComponent.WEAPON_HT2; // Two Hand-to-Hand
} else {
cof.wclass = CofComponent.WEAPON_HTH;
Gdx.app.error(TAG, String.format(
"Unknown weapon combination: LH=%s RH=%s", LHEntry.wclass, RHEntry.wclass));
}
} else if (LH != null || RH != null) {
RH = ObjectUtils.firstNonNull(RH, LH);
LH = null;
if (RH.type.is(com.riiablo.item.Type.BOW)) {
LH = RH;
RH = null;
Weapons.Entry LHEntry = LH.getBase();
cof.wclass = Riiablo.files.WeaponClass.index(LHEntry.wclass);
} else if (RH.type.is(com.riiablo.item.Type.WEAP)) { // make sure weap and not e.g. misl, might not be required
Weapons.Entry RHEntry = RH.getBase();
cof.wclass = Riiablo.files.WeaponClass.index(RHEntry.wclass);
} else {
cof.wclass = CofComponent.WEAPON_HTH;
}
} else {
cof.wclass = CofComponent.WEAPON_HTH;
}
cof.component[COF.Component.RH] = RH != null ? TypeComponent.Type.PLR.getComponent(RH.base.alternateGfx) : CofComponent.COMPONENT_NIL;
cof.component[COF.Component.LH] = LH != null ? TypeComponent.Type.PLR.getComponent(LH.base.alternateGfx) : CofComponent.COMPONENT_NIL;
cof.component[COF.Component.SH] = SH != null ? TypeComponent.Type.PLR.getComponent(SH.base.alternateGfx) : CofComponent.COMPONENT_NIL;
cof.alpha[COF.Component.RH] = RH != null && RH.isEthereal() ? Item.ETHEREAL_ALPHA : CofComponent.ALPHA_NULL;
cof.alpha[COF.Component.LH] = LH != null && LH.isEthereal() ? Item.ETHEREAL_ALPHA : CofComponent.ALPHA_NULL;
cof.alpha[COF.Component.SH] = SH != null && SH.isEthereal() ? Item.ETHEREAL_ALPHA : CofComponent.ALPHA_NULL;
com.riiablo.engine.Engine.getOrCreateComponent(entity, getEngine(), AlphaUpdate.class, this.alphaUpdate).flags |= BodyLoc.RARM.components();
}
private void updateArmorClass(Entity entity, CharData charData, CofComponent cof) {
Item head = charData.getEquipped(BodyLoc.HEAD);
cof.component[COF.Component.HD] = head != null ? TypeComponent.Type.PLR.getComponent(head.base.alternateGfx) : CofComponent.COMPONENT_LIT;
cof.transform[COF.Component.HD] = head != null ? (byte) ((head.base.Transform << 5) | (head.charColorIndex & 0x1F)) : CofComponent.TRANSFORM_NULL;
TransformUpdate transformUpdate = com.riiablo.engine.Engine.getOrCreateComponent(entity, getEngine(), TransformUpdate.class, this.transformUpdate);
transformUpdate.flags |= BodyLoc.HEAD.components();
Item body = charData.getEquipped(BodyLoc.TORS);
if (body != null) {
Armor.Entry armor = body.getBase();
cof.component[COF.Component.TR] = (armor.Torso + 1);
cof.component[COF.Component.LG] = (armor.Legs + 1);
cof.component[COF.Component.RA] = (armor.rArm + 1);
cof.component[COF.Component.LA] = (armor.lArm + 1);
cof.component[COF.Component.S1] = (armor.lSPad + 1);
cof.component[COF.Component.S2] = (armor.rSPad + 1);
byte packedTransform = (byte) ((body.base.Transform << 5) | (body.charColorIndex & 0x1F));
cof.transform[COF.Component.TR] = packedTransform;
cof.transform[COF.Component.LG] = packedTransform;
cof.transform[COF.Component.RA] = packedTransform;
cof.transform[COF.Component.LA] = packedTransform;
cof.transform[COF.Component.S1] = packedTransform;
cof.transform[COF.Component.S2] = packedTransform;
transformUpdate.flags |= BodyLoc.TORS.components();
} else {
cof.component[COF.Component.TR] = CofComponent.COMPONENT_LIT;
cof.component[COF.Component.LG] = CofComponent.COMPONENT_LIT;
cof.component[COF.Component.RA] = CofComponent.COMPONENT_LIT;
cof.component[COF.Component.LA] = CofComponent.COMPONENT_LIT;
cof.component[COF.Component.S1] = CofComponent.COMPONENT_LIT;
cof.component[COF.Component.S2] = CofComponent.COMPONENT_LIT;
cof.transform[COF.Component.TR] = CofComponent.TRANSFORM_NULL;
cof.transform[COF.Component.LG] = CofComponent.TRANSFORM_NULL;
cof.transform[COF.Component.RA] = CofComponent.TRANSFORM_NULL;
cof.transform[COF.Component.LA] = CofComponent.TRANSFORM_NULL;
cof.transform[COF.Component.S1] = CofComponent.TRANSFORM_NULL;
cof.transform[COF.Component.S2] = CofComponent.TRANSFORM_NULL;
transformUpdate.flags |= BodyLoc.TORS.components();
}
}
@Override
public void onChanged(CharData client, BodyLoc bodyLoc, Item oldItem, Item item) {
Entity entity = charDatas.get(client);
CofComponent cofComponent = this.cofComponent.get(entity);
cofComponent.dirty |= bodyLoc.components();
updateWeaponClass(entity, client, cofComponent);
updateArmorClass(entity, client, cofComponent);
}
@Override
public void onAlternated(CharData client, int alternate, Item LH, Item RH) {
Entity entity = charDatas.get(client);
CofComponent cofComponent = this.cofComponent.get(entity);
updateWeaponClass(entity, client, cofComponent);
updateArmorClass(entity, client, cofComponent);
}
}

View File

@ -0,0 +1,33 @@
package com.riiablo.engine.system;
import com.badlogic.ashley.core.ComponentMapper;
import com.badlogic.ashley.core.Entity;
import com.badlogic.ashley.core.Family;
import com.badlogic.ashley.systems.IteratingSystem;
import com.riiablo.engine.Engine;
import com.riiablo.engine.component.MapComponent;
import com.riiablo.engine.component.PositionComponent;
import com.riiablo.engine.component.ZoneAwareComponent;
import com.riiablo.engine.component.ZoneUpdate;
import com.riiablo.map.Map;
public class ZoneSystem extends IteratingSystem {
private final ComponentMapper<ZoneUpdate> zoneUpdateComponent = ComponentMapper.getFor(ZoneUpdate.class);
private final ComponentMapper<PositionComponent> positionComponent = ComponentMapper.getFor(PositionComponent.class);
private final ComponentMapper<MapComponent> mapComponent = ComponentMapper.getFor(MapComponent.class);
public ZoneSystem() {
super(Family.all(ZoneAwareComponent.class, PositionComponent.class, MapComponent.class).get());
}
@Override
protected void processEntity(Entity entity, float delta) {
PositionComponent positionComponent = this.positionComponent.get(entity);
MapComponent mapComponent = this.mapComponent.get(entity);
Map.Zone zone = mapComponent.map.getZone(positionComponent.position);
if (zone != mapComponent.zone) {
mapComponent.zone = zone;
Engine.getOrCreateComponent(entity, getEngine(), ZoneUpdate.class, zoneUpdateComponent);
}
}
}

View File

@ -0,0 +1,42 @@
package com.riiablo.engine.system;
import com.badlogic.ashley.core.ComponentMapper;
import com.badlogic.ashley.core.Entity;
import com.badlogic.ashley.core.Family;
import com.badlogic.ashley.systems.IteratingSystem;
import com.riiablo.engine.Engine;
import com.riiablo.engine.component.MapComponent;
import com.riiablo.engine.component.MovementModeComponent;
import com.riiablo.engine.component.PlayerComponent;
import com.riiablo.engine.component.ZoneUpdate;
import com.riiablo.map.Map;
public class ZoneUpdateSystem extends IteratingSystem {
private final ComponentMapper<MapComponent> mapComponent = ComponentMapper.getFor(MapComponent.class);
private final ComponentMapper<PlayerComponent> playerComponent = ComponentMapper.getFor(PlayerComponent.class);
private final ComponentMapper<MovementModeComponent> movementModeComponent = ComponentMapper.getFor(MovementModeComponent.class);
public ZoneUpdateSystem() {
super(Family.all(ZoneUpdate.class, MapComponent.class, MovementModeComponent.class).get());
}
@Override
protected void processEntity(Entity entity, float delta) {
MapComponent mapComponent = this.mapComponent.get(entity);
Map.Zone zone = mapComponent.zone;
if (playerComponent.has(entity)) {
MovementModeComponent movementModeComponent = this.movementModeComponent.get(entity);
if (zone.isTown()) {
movementModeComponent.NU = Engine.Player.MODE_TN;
movementModeComponent.WL = Engine.Player.MODE_TW;
movementModeComponent.RN = Engine.Player.MODE_RN;
} else {
movementModeComponent.NU = Engine.Player.MODE_NU;
movementModeComponent.WL = Engine.Player.MODE_WL;
movementModeComponent.RN = Engine.Player.MODE_RN;
}
}
entity.remove(ZoneUpdate.class);
}
}