added snakes falling, buggy enemy attacks, GOAP not working correclty
This commit is contained in:
parent
07665e0e6f
commit
d4cdfa82f4
|
@ -8,7 +8,7 @@
|
||||||
"animationSprite": "slice",
|
"animationSprite": "slice",
|
||||||
"spriteKey": "knife",
|
"spriteKey": "knife",
|
||||||
"damage": 50,
|
"damage": 50,
|
||||||
"cooldown": 3,
|
"cooldown": 30,
|
||||||
"useVolume": 0
|
"useVolume": 0
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -105,15 +105,10 @@ export default class EnemyAI extends StateMachineGoapAI implements BattlerAI {
|
||||||
this.planner = new GoapActionPlanner();
|
this.planner = new GoapActionPlanner();
|
||||||
|
|
||||||
//TODO - get correct tilemap
|
//TODO - get correct tilemap
|
||||||
//this.tilemap = this.owner.getScene().getTilemap(options.tilemap) as OrthogonalTilemap;
|
|
||||||
this.tilemap = <OrthogonalTilemap>this.owner.getScene().getLayer("Wall").getItems()[0];
|
this.tilemap = <OrthogonalTilemap>this.owner.getScene().getLayer("Wall").getItems()[0];
|
||||||
//this.tilemap = <OrthogonalTilemap>this.owner.getScene().getTilemap("Main");
|
|
||||||
|
|
||||||
// Initialize to the default state
|
// Initialize to the default state
|
||||||
this.initialize(EnemyStates.DEFAULT);
|
this.initialize(EnemyStates.DEFAULT);
|
||||||
|
|
||||||
//this.getPlayerPosition();
|
|
||||||
|
|
||||||
this.direction = 1; //default moving to the right
|
this.direction = 1; //default moving to the right
|
||||||
|
|
||||||
//exp value
|
//exp value
|
||||||
|
@ -158,9 +153,9 @@ export default class EnemyAI extends StateMachineGoapAI implements BattlerAI {
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO - need to modify for side view
|
//TODO - need to modify for side view
|
||||||
/*
|
|
||||||
isPlayerVisible(pos: Vec2): Vec2{
|
isPlayerVisible(pos: Vec2): Vec2{
|
||||||
//Check if one player is visible, taking into account walls
|
//Check ifplayer is visible, taking into account walls
|
||||||
|
|
||||||
// Get the new player location
|
// Get the new player location
|
||||||
let start = this.owner.position.clone();
|
let start = this.owner.position.clone();
|
||||||
|
@ -173,7 +168,7 @@ export default class EnemyAI extends StateMachineGoapAI implements BattlerAI {
|
||||||
let maxY = Math.max(start.y, pos.y);
|
let maxY = Math.max(start.y, pos.y);
|
||||||
|
|
||||||
// Get the wall tilemap
|
// Get the wall tilemap
|
||||||
let walls = <OrthogonalTilemap>this.owner.getScene().getLayer("Wall").getItems()[0];
|
let walls = this.tilemap
|
||||||
|
|
||||||
let minIndex = walls.getColRowAt(new Vec2(minX, minY));
|
let minIndex = walls.getColRowAt(new Vec2(minX, minY));
|
||||||
let maxIndex = walls.getColRowAt(new Vec2(maxX, maxY));
|
let maxIndex = walls.getColRowAt(new Vec2(maxX, maxY));
|
||||||
|
@ -193,6 +188,7 @@ export default class EnemyAI extends StateMachineGoapAI implements BattlerAI {
|
||||||
|
|
||||||
if (hit !== null && start.distanceSqTo(hit.pos) < start.distanceSqTo(pos)) {
|
if (hit !== null && start.distanceSqTo(hit.pos) < start.distanceSqTo(pos)) {
|
||||||
// We hit a wall, we can't see the player
|
// We hit a wall, we can't see the player
|
||||||
|
console.log("player not visible")
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -201,10 +197,21 @@ export default class EnemyAI extends StateMachineGoapAI implements BattlerAI {
|
||||||
|
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gets the position of the player
|
||||||
|
* @returns position of the player if visible, else null
|
||||||
*/
|
*/
|
||||||
|
getPlayerPosition(): Vec2 {
|
||||||
|
//TODO - check if player is visible
|
||||||
|
if(this.isPlayerVisible(this.player.position))
|
||||||
|
return this.player.position;
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
update(deltaT: number){
|
update(deltaT: number){
|
||||||
if (InputWrapper.getState() != GameState.GAMING) {
|
if (InputWrapper.getState() != GameState.GAMING) {
|
||||||
this.owner.animation.pause();
|
this.owner.animation.pause();
|
||||||
|
@ -214,12 +221,18 @@ export default class EnemyAI extends StateMachineGoapAI implements BattlerAI {
|
||||||
super.update(deltaT);
|
super.update(deltaT);
|
||||||
|
|
||||||
// This is the plan that is executed in the Active state, so whenever we don't have a plan, acquire a new one given the current statuses the enemy has
|
// This is the plan that is executed in the Active state, so whenever we don't have a plan, acquire a new one given the current statuses the enemy has
|
||||||
/*
|
|
||||||
if (this.plan.isEmpty()) {
|
if (this.plan.isEmpty()) {
|
||||||
//get a new plan
|
//get a new plan
|
||||||
|
if(this.possibleActions === undefined){
|
||||||
|
console.log("undefined possiblse actions");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.currentState === undefined){
|
||||||
|
console.log("undefined current status");
|
||||||
|
}
|
||||||
this.plan = this.planner.plan(Statuses.REACHED_GOAL, this.possibleActions, this.currentStatus, null);
|
this.plan = this.planner.plan(Statuses.REACHED_GOAL, this.possibleActions, this.currentStatus, null);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
//TODO
|
//TODO
|
||||||
if(this.burnTimer.isStopped() && this.burnCounter >0){
|
if(this.burnTimer.isStopped() && this.burnCounter >0){
|
||||||
|
@ -237,6 +250,25 @@ export default class EnemyAI extends StateMachineGoapAI implements BattlerAI {
|
||||||
this.bleedTimer.start();
|
this.bleedTimer.start();
|
||||||
this.damage(5 + (<PlayerController>this.player._ai).extraDotDmg + (<PlayerController>this.player._ai).CURRENT_ATK * .08);
|
this.damage(5 + (<PlayerController>this.player._ai).extraDotDmg + (<PlayerController>this.player._ai).CURRENT_ATK * .08);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//TODO - GOAP NOT WORKING, ATTACK WORKAROUND
|
||||||
|
if(this.getPlayerPosition() == null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let distance = this.owner.position.distanceTo(this.getPlayerPosition());
|
||||||
|
if( distance <= 60){
|
||||||
|
if( this.direction == Math.sign(this.getPlayerPosition().x -this.owner.position.x) ){
|
||||||
|
let dir = this.getPlayerPosition().clone().sub(this.owner.position).normalize();
|
||||||
|
if(this.weapon.use(this.owner, "enemy", dir.scale(1,0))){
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
47
src/shattered_sword/AI/EnemyActions/AttackAction.ts
Normal file
47
src/shattered_sword/AI/EnemyActions/AttackAction.ts
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
import StateMachineGoapAI from "../../../Wolfie2D/AI/StateMachineGoapAI";
|
||||||
|
import GoapAction from "../../../Wolfie2D/DataTypes/Interfaces/GoapAction";
|
||||||
|
import Vec2 from "../../../Wolfie2D/DataTypes/Vec2";
|
||||||
|
import Emitter from "../../../Wolfie2D/Events/Emitter";
|
||||||
|
import GameNode from "../../../Wolfie2D/Nodes/GameNode";
|
||||||
|
import EnemyAI from "../EnemyAI";
|
||||||
|
|
||||||
|
export default class AttackAction extends GoapAction {
|
||||||
|
protected emitter: Emitter;
|
||||||
|
|
||||||
|
constructor(cost: number, preconditions: Array<string>, effects: Array<string>, options?: Record<string, any>) {
|
||||||
|
super();
|
||||||
|
this.cost = cost;
|
||||||
|
this.preconditions = preconditions;
|
||||||
|
this.effects = effects;
|
||||||
|
}
|
||||||
|
|
||||||
|
performAction(statuses: Array<string>, actor: StateMachineGoapAI, deltaT: number, target?: StateMachineGoapAI): Array<string> {
|
||||||
|
//Check if preconditions are met for this action to be performed
|
||||||
|
if (this.checkPreconditions(statuses)){
|
||||||
|
let enemy = <EnemyAI>actor;
|
||||||
|
|
||||||
|
//If the player is out of sight, don't bother attacking
|
||||||
|
if (enemy.getPlayerPosition() == null){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Randomize attack direction, gives the enemy gun users stormtrooper aim
|
||||||
|
let dir = enemy.getPlayerPosition().clone().sub(enemy.owner.position).normalize();
|
||||||
|
dir.rotateCCW(Math.PI / 4 * Math.random() - Math.PI/8);
|
||||||
|
if(enemy.weapon.use(enemy.owner, "enemy", dir)){
|
||||||
|
// If we fired, face that direction
|
||||||
|
enemy.owner.rotation = Vec2.UP.angleToCCW(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.effects;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateCost(options: Record<string, number>): void {}
|
||||||
|
|
||||||
|
toString(): string {
|
||||||
|
return "(AttackAction)";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
47
src/shattered_sword/AI/EnemyActions/Move.ts
Normal file
47
src/shattered_sword/AI/EnemyActions/Move.ts
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
import StateMachineGoapAI from "../../../Wolfie2D/AI/StateMachineGoapAI";
|
||||||
|
import GoapAction from "../../../Wolfie2D/DataTypes/Interfaces/GoapAction";
|
||||||
|
import Vec2 from "../../../Wolfie2D/DataTypes/Vec2";
|
||||||
|
import Emitter from "../../../Wolfie2D/Events/Emitter";
|
||||||
|
import NavigationPath from "../../../Wolfie2D/Pathfinding/NavigationPath";
|
||||||
|
import EnemyAI from "../EnemyAI";
|
||||||
|
|
||||||
|
export default class Move extends GoapAction {
|
||||||
|
private inRange: number;
|
||||||
|
|
||||||
|
private path: NavigationPath;
|
||||||
|
protected emitter: Emitter;
|
||||||
|
|
||||||
|
constructor(cost: number, preconditions: Array<string>, effects: Array<string>, options?: Record<string, any>) {
|
||||||
|
super();
|
||||||
|
this.cost = cost;
|
||||||
|
this.preconditions = preconditions;
|
||||||
|
this.effects = effects;
|
||||||
|
this.loopAction = true;
|
||||||
|
this.inRange = options.inRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
performAction(statuses: Array<string>, actor: StateMachineGoapAI, deltaT: number, target?: StateMachineGoapAI): Array<string> {
|
||||||
|
if (this.checkPreconditions(statuses)){
|
||||||
|
//Check distance from player
|
||||||
|
let enemy = <EnemyAI>actor;
|
||||||
|
let playerPos = enemy.lastPlayerPos;
|
||||||
|
let distance = enemy.owner.position.distanceTo(playerPos);
|
||||||
|
|
||||||
|
//If close enough, we've moved far enough and this loop action is done
|
||||||
|
if (distance <= this.inRange){
|
||||||
|
return this.effects;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Otherwise move
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return this.effects;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateCost(options: Record<string, number>): void {}
|
||||||
|
|
||||||
|
toString(): string {
|
||||||
|
return "(Move)";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -42,23 +42,15 @@ export default class Patrol extends EnemyState {
|
||||||
//check if next tile on walking path is collidable
|
//check if next tile on walking path is collidable
|
||||||
if(this.parent.tilemap.isTileCollidable(colrow.x+this.parent.direction,colrow.y) || this.parent.tilemap.isTileCollidable(colrow.x+this.parent.direction,colrow.y-1)){
|
if(this.parent.tilemap.isTileCollidable(colrow.x+this.parent.direction,colrow.y) || this.parent.tilemap.isTileCollidable(colrow.x+this.parent.direction,colrow.y-1)){
|
||||||
//turn around
|
//turn around
|
||||||
//console.log(this.parent.tilemap.getTileAtRowCol(colrow));
|
|
||||||
this.parent.direction *= -1;
|
this.parent.direction *= -1;
|
||||||
//console.log((<Sprite>this.owner).invertX);
|
|
||||||
//(<Sprite>this.owner).invertX != (<Sprite>this.owner).invertX ;
|
|
||||||
//console.log("turn around cus wall in front");
|
|
||||||
}
|
}
|
||||||
//check if next ground tile is collidable
|
//check if next ground tile is collidable
|
||||||
else if(!this.parent.tilemap.isTileCollidable(colrow.x+this.parent.direction,colrow.y+1)){
|
else if(!this.parent.tilemap.isTileCollidable(colrow.x+this.parent.direction,colrow.y+1)){
|
||||||
//turn around
|
//turn around
|
||||||
this.parent.direction *=-1;
|
this.parent.direction *=-1;
|
||||||
//console.log((<Sprite>this.owner).invertX);
|
|
||||||
//console.log("turn around cus no floor in front");
|
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
//keep moving
|
//keep moving
|
||||||
//this.velocity.x = this.speed;
|
|
||||||
//console.log("there is floor ahead");
|
|
||||||
}
|
}
|
||||||
//move
|
//move
|
||||||
this.parent.velocity.x = this.parent.direction * this.parent.speed;
|
this.parent.velocity.x = this.parent.direction * this.parent.speed;
|
||||||
|
|
|
@ -21,7 +21,7 @@ export default class Slice extends WeaponType {
|
||||||
// TODO - need to rotate the anim properly
|
// TODO - need to rotate the anim properly
|
||||||
//sliceSprite.rotation = attacker.rotation;
|
//sliceSprite.rotation = attacker.rotation;
|
||||||
//sliceSprite.rotation = (<Sprite>attacker).invertX? .5* Math.PI : 1.5 * Math.PI;
|
//sliceSprite.rotation = (<Sprite>attacker).invertX? .5* Math.PI : 1.5 * Math.PI;
|
||||||
sliceSprite.invertX = (<Sprite>attacker).invertX;
|
//sliceSprite.invertX = (<Sprite>attacker).invertX;
|
||||||
|
|
||||||
//TODO-
|
//TODO-
|
||||||
//4 to scale up the default sprite - may be different later depending on atk anim
|
//4 to scale up the default sprite - may be different later depending on atk anim
|
||||||
|
|
|
@ -52,7 +52,8 @@ export enum BuffType {
|
||||||
LIFESTEAL = "lifesteal",
|
LIFESTEAL = "lifesteal",
|
||||||
LIFESTEALBUFF = "lifestealbuff",
|
LIFESTEALBUFF = "lifestealbuff",
|
||||||
EXTRALIFE= "extralife",
|
EXTRALIFE= "extralife",
|
||||||
ONESHOT = "oneshot"
|
ONESHOT = "oneshot",
|
||||||
|
JUMP = "jump"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -128,6 +129,8 @@ export default class PlayerController extends StateMachineAI implements BattlerA
|
||||||
lifestealratio : number = 0; //percent of damage to steal
|
lifestealratio : number = 0; //percent of damage to steal
|
||||||
hasOneShot: Boolean = false;
|
hasOneShot: Boolean = false;
|
||||||
extraDotDmg : number =0;
|
extraDotDmg : number =0;
|
||||||
|
lives: number = 1;
|
||||||
|
cooldownMultiplier : number = 1;
|
||||||
|
|
||||||
//TODO - add new buffs here
|
//TODO - add new buffs here
|
||||||
CURRENT_BUFFS: {
|
CURRENT_BUFFS: {
|
||||||
|
@ -140,7 +143,6 @@ export default class PlayerController extends StateMachineAI implements BattlerA
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//TODO - get the correct tilemap
|
//TODO - get the correct tilemap
|
||||||
initializeAI(owner: GameNode, options: Record<string, any>){
|
initializeAI(owner: GameNode, options: Record<string, any>){
|
||||||
this.owner = owner;
|
this.owner = owner;
|
||||||
|
@ -260,6 +262,7 @@ export default class PlayerController extends StateMachineAI implements BattlerA
|
||||||
this.invincible = true;
|
this.invincible = true;
|
||||||
//console.log("hurt anim");
|
//console.log("hurt anim");
|
||||||
(<AnimatedSprite>this.owner).animation.play("HURT" );
|
(<AnimatedSprite>this.owner).animation.play("HURT" );
|
||||||
|
damage /= this.BASE_DEF/ this.CURRENT_DEF;
|
||||||
this.CURRENT_HP -= damage;
|
this.CURRENT_HP -= damage;
|
||||||
//if player has shield buff give them shield when damaged
|
//if player has shield buff give them shield when damaged
|
||||||
if(this.hasShield){
|
if(this.hasShield){
|
||||||
|
@ -276,6 +279,7 @@ export default class PlayerController extends StateMachineAI implements BattlerA
|
||||||
if(this.CURRENT_HP <= 0){
|
if(this.CURRENT_HP <= 0){
|
||||||
(<AnimatedSprite>this.owner).animation.play("DYING");
|
(<AnimatedSprite>this.owner).animation.play("DYING");
|
||||||
(<AnimatedSprite>this.owner).animation.queue("DEAD", true, Player_Events.PLAYER_KILLED);
|
(<AnimatedSprite>this.owner).animation.queue("DEAD", true, Player_Events.PLAYER_KILLED);
|
||||||
|
this.emitter.fireEvent(Player_Events.PLAYER_KILLED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -331,14 +335,14 @@ export default class PlayerController extends StateMachineAI implements BattlerA
|
||||||
{type:BuffType.ATKSPEED, value:num, category: BuffCategory.ATTACK},
|
{type:BuffType.ATKSPEED, value:num, category: BuffCategory.ATTACK},
|
||||||
];
|
];
|
||||||
if(!this.hasDoubleStrike){
|
if(!this.hasDoubleStrike){
|
||||||
attackBuffs.push({type:BuffType.DOUBLESTRIKE, value:num, category: BuffCategory.ATTACK, string:"your attacks are followed by a weaker strike"});
|
attackBuffs.push({type:BuffType.DOUBLESTRIKE, value:num, category: BuffCategory.ATTACK, string:"your attacks are \nfollowed by a \nweaker strike"});
|
||||||
}
|
}
|
||||||
|
|
||||||
let dotBuffs : Buff[] = [
|
let dotBuffs : Buff[] = [
|
||||||
{type:BuffType.BLEED, value:1, category: BuffCategory.DOT, string: "Your hits apply Bleed"},
|
{type:BuffType.BLEED, value:1, category: BuffCategory.DOT, string: "Your hits \napply Bleed"},
|
||||||
{type:BuffType.BURN, value:1, category: BuffCategory.DOT, string: "Your hits apply Burn"},
|
{type:BuffType.BURN, value:1, category: BuffCategory.DOT, string: "Your hits \napply Burn"},
|
||||||
{type:BuffType.POISON, value:1, category: BuffCategory.DOT, string: "Your hits apply poison"},
|
{type:BuffType.POISON, value:1, category: BuffCategory.DOT, string: "Your hits \napply poison"},
|
||||||
{type:BuffType.EXTRA_DOT, value:num, category: BuffCategory.DOT, string: "increase your DOT damage"},
|
{type:BuffType.EXTRA_DOT, value:num, category: BuffCategory.DOT, string: "increase your \nDOT damage"},
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -347,10 +351,10 @@ export default class PlayerController extends StateMachineAI implements BattlerA
|
||||||
];
|
];
|
||||||
//if player doesnt have shield buff, give them the option, otherwise give buff shield option
|
//if player doesnt have shield buff, give them the option, otherwise give buff shield option
|
||||||
if(!this.hasShield){
|
if(!this.hasShield){
|
||||||
shieldBuffs.push({type:BuffType.SHIELD, value:1, category: BuffCategory.SHIELD, string: "Gain Shield When Damaged"});
|
shieldBuffs.push({type:BuffType.SHIELD, value:1, category: BuffCategory.SHIELD, string: "Gain Shield \nWhen Damaged \n Shields return \nthe damage taken \nto attacker"});
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
shieldBuffs.push({type:BuffType.SHIELD_DMG, value:num, category: BuffCategory.SHIELD});
|
shieldBuffs.push({type:BuffType.SHIELD_DMG, value:num, category: BuffCategory.SHIELD, string: "increase damage \nreturned by shield"});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -361,17 +365,17 @@ export default class PlayerController extends StateMachineAI implements BattlerA
|
||||||
healthBuffs.push({type:BuffType.LIFESTEAL, value:1, category: BuffCategory.HEALTH, string:"Gain lifesteal"});
|
healthBuffs.push({type:BuffType.LIFESTEAL, value:1, category: BuffCategory.HEALTH, string:"Gain lifesteal"});
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
healthBuffs.push({type:BuffType.LIFESTEALBUFF, value:num, category: BuffCategory.HEALTH});
|
healthBuffs.push({type:BuffType.LIFESTEALBUFF, value:num/10, category: BuffCategory.HEALTH, string:"Increase Lifesteal \nstrength by "+ num+ "%"});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let extraBuffs : Buff[] = [
|
let extraBuffs : Buff[] = [
|
||||||
{type:BuffType.EXTRALIFE, value:1, category: BuffCategory.EXTRA, string: "Gain an Extra Life"},
|
{type:BuffType.EXTRALIFE, value:1, category: BuffCategory.EXTRA, string: "Gain an \nExtra Life"},
|
||||||
{type:BuffType.SPEED, value:num, category: BuffCategory.EXTRA},
|
{type:BuffType.SPEED, value:num, category: BuffCategory.EXTRA},
|
||||||
{type:BuffType.ATK, value:num, category: BuffCategory.EXTRA}
|
{type:BuffType.ATK, value:num, category: BuffCategory.EXTRA}
|
||||||
];
|
];
|
||||||
if(!this.hasOneShot){
|
if(!this.hasOneShot){
|
||||||
extraBuffs.push({type:BuffType.ONESHOT, value:1, category: BuffCategory.EXTRA, string: "Your hits hurt 100x more but you die in one shot"});
|
extraBuffs.push({type:BuffType.ONESHOT, value:1, category: BuffCategory.EXTRA, string: "Your hits hurt \n100x more but \nyour max health \nis set to 1 "});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -460,20 +464,26 @@ export default class PlayerController extends StateMachineAI implements BattlerA
|
||||||
|
|
||||||
case BuffType.ATKSPEED:
|
case BuffType.ATKSPEED:
|
||||||
if (item) {
|
if (item) {
|
||||||
|
this.cooldownMultiplier -= buff.value;
|
||||||
//reduce cooldowntimer
|
//reduce cooldowntimer
|
||||||
//(<Weapon>item).cooldownTimer
|
(<Weapon>item).cooldownTimer = new Timer((<Weapon>item).cooldown * this.cooldownMultiplier )
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case BuffType.DOUBLESTRIKE:
|
case BuffType.DOUBLESTRIKE:
|
||||||
|
//TODO -
|
||||||
break;
|
break;
|
||||||
case BuffType.SHIELD_DMG:
|
case BuffType.SHIELD_DMG:
|
||||||
this.shieldDamage += buff.value/10 ;
|
this.shieldDamage += buff.value/10 ;
|
||||||
break;
|
break;
|
||||||
case BuffType.EXTRALIFE:
|
case BuffType.EXTRALIFE:
|
||||||
|
this.lives ++;
|
||||||
break;
|
break;
|
||||||
case BuffType.LIFESTEAL:
|
case BuffType.LIFESTEAL:
|
||||||
this.hasLifesteal = true;
|
this.hasLifesteal = true;
|
||||||
|
this.lifestealratio = .2; //20% lifesteal
|
||||||
|
break;
|
||||||
|
case BuffType.LIFESTEALBUFF:
|
||||||
|
this.lifestealratio += buff.value;
|
||||||
break;
|
break;
|
||||||
case BuffType.ONESHOT:
|
case BuffType.ONESHOT:
|
||||||
this.MAX_HP = 1;
|
this.MAX_HP = 1;
|
||||||
|
|
|
@ -36,8 +36,9 @@ import Sprite from "../../Wolfie2D/Nodes/Sprites/Sprite";
|
||||||
import Platformer from "../../demos/Platformer";
|
import Platformer from "../../demos/Platformer";
|
||||||
import TextInput from "../../Wolfie2D/Nodes/UIElements/TextInput";
|
import TextInput from "../../Wolfie2D/Nodes/UIElements/TextInput";
|
||||||
import { TiledTilemapData } from "../../Wolfie2D/DataTypes/Tilesets/TiledData";
|
import { TiledTilemapData } from "../../Wolfie2D/DataTypes/Tilesets/TiledData";
|
||||||
|
import AttackAction from "../AI/EnemyActions/AttackAction";
|
||||||
|
import Move from "../AI/EnemyActions/Move";
|
||||||
|
import GameOver from "./GameOver";
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
/**
|
/**
|
||||||
|
@ -286,7 +287,12 @@ export default class GameLevel extends Scene {
|
||||||
console.log("player Died");
|
console.log("player Died");
|
||||||
(<AnimatedSprite>this.player).animation.play("DEAD", false);
|
(<AnimatedSprite>this.player).animation.play("DEAD", false);
|
||||||
InputWrapper.disableInput();
|
InputWrapper.disableInput();
|
||||||
|
if((<PlayerController>this.player._ai).lives >0){
|
||||||
this.respawnPlayer();
|
this.respawnPlayer();
|
||||||
|
}
|
||||||
|
else{ //no more lives
|
||||||
|
this.sceneManager.changeToScene(GameOver, {});
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -344,10 +350,6 @@ export default class GameLevel extends Scene {
|
||||||
// this.expLabel.sizeToText();
|
// this.expLabel.sizeToText();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//handle collisions - may be in battle manager instead
|
|
||||||
|
|
||||||
//move background
|
//move background
|
||||||
|
|
||||||
// Get the viewport center and padded size
|
// Get the viewport center and padded size
|
||||||
|
@ -379,6 +381,24 @@ export default class GameLevel extends Scene {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//spawn snake()
|
||||||
|
if(Math.random() < .002){
|
||||||
|
console.log("RANDOM SNAKE!");
|
||||||
|
this.addEnemy("Snake", this.player.position.clone().add(new Vec2(0,-320)),{
|
||||||
|
player: this.player,
|
||||||
|
health: 50,
|
||||||
|
tilemap: "Main",
|
||||||
|
goal: Statuses.REACHED_GOAL,
|
||||||
|
size: new Vec2(16,16),
|
||||||
|
offset : new Vec2(0, 16),
|
||||||
|
exp: 50,
|
||||||
|
actions: [new AttackAction(3, [Statuses.IN_RANGE], [Statuses.REACHED_GOAL]),
|
||||||
|
new Move(2, [], [Statuses.IN_RANGE], {inRange: 60})],
|
||||||
|
status : [Statuses.CAN_RETREAT, Statuses.CAN_BERSERK],
|
||||||
|
weapon : this.createWeapon("knife")
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO put UI changes in here
|
// TODO put UI changes in here
|
||||||
|
@ -403,7 +423,7 @@ export default class GameLevel extends Scene {
|
||||||
// Add a layer for players and enemies
|
// Add a layer for players and enemies
|
||||||
this.addLayer("primary", 1);
|
this.addLayer("primary", 1);
|
||||||
|
|
||||||
this.buffLayer = this.addUILayer("buffLayer"); //TODO - test depth later, may be just a regular Layer
|
this.buffLayer = this.addUILayer("buffLayer");
|
||||||
|
|
||||||
|
|
||||||
this.storyLayer = this.addUILayer("story");
|
this.storyLayer = this.addUILayer("story");
|
||||||
|
@ -708,7 +728,19 @@ export default class GameLevel extends Scene {
|
||||||
enemy.addAI(EnemyAI, aiOptions); //TODO - add individual enemy AI
|
enemy.addAI(EnemyAI, aiOptions); //TODO - add individual enemy AI
|
||||||
enemy.setGroup("Enemy");
|
enemy.setGroup("Enemy");
|
||||||
enemy.setTrigger("player", Player_Events.PLAYER_COLLIDE, null);
|
enemy.setTrigger("player", Player_Events.PLAYER_COLLIDE, null);
|
||||||
|
let actionsDefault = [new AttackAction(3, [Statuses.IN_RANGE], [Statuses.REACHED_GOAL]),
|
||||||
|
new Move(2, [], [Statuses.IN_RANGE], {inRange: 60}),
|
||||||
|
];
|
||||||
|
|
||||||
|
let statusArray : Array<string> = [Statuses.CAN_RETREAT, Statuses.CAN_BERSERK];
|
||||||
|
|
||||||
|
//TODO - not working correctly
|
||||||
|
if ( "status" !in aiOptions ){
|
||||||
|
aiOptions["status"] = statusArray;
|
||||||
|
}
|
||||||
|
if( "actions" !in aiOptions){
|
||||||
|
aiOptions["actions"] = actionsDefault;
|
||||||
|
}
|
||||||
//add enemy to the enemy array
|
//add enemy to the enemy array
|
||||||
this.enemies.push(enemy);
|
this.enemies.push(enemy);
|
||||||
//this.battleManager.setEnemies(this.enemies.map(enemy => <BattlerAI>enemy._ai));
|
//this.battleManager.setEnemies(this.enemies.map(enemy => <BattlerAI>enemy._ai));
|
||||||
|
@ -716,7 +748,16 @@ export default class GameLevel extends Scene {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//TODO - give each enemy unique weapon
|
||||||
protected initializeEnemies( enemies: Enemy[]){
|
protected initializeEnemies( enemies: Enemy[]){
|
||||||
|
|
||||||
|
|
||||||
|
let actionsDefault = [new AttackAction(3, [Statuses.IN_RANGE], [Statuses.REACHED_GOAL]),
|
||||||
|
new Move(2, [], [Statuses.IN_RANGE], {inRange: 60}),
|
||||||
|
];
|
||||||
|
|
||||||
|
let statusArray : Array<string> = [Statuses.CAN_RETREAT, Statuses.CAN_BERSERK];
|
||||||
|
|
||||||
for (let enemy of enemies) {
|
for (let enemy of enemies) {
|
||||||
switch (enemy.type) {
|
switch (enemy.type) {
|
||||||
case "test_dummy":
|
case "test_dummy":
|
||||||
|
@ -724,11 +765,12 @@ export default class GameLevel extends Scene {
|
||||||
player: this.player,
|
player: this.player,
|
||||||
health: 100,
|
health: 100,
|
||||||
tilemap: "Main",
|
tilemap: "Main",
|
||||||
//actions:actions,
|
actions: actionsDefault,
|
||||||
|
status: statusArray,
|
||||||
goal: Statuses.REACHED_GOAL,
|
goal: Statuses.REACHED_GOAL,
|
||||||
//TODO - test Add collision shape for each enemy type
|
|
||||||
//size: new AABB(Vec2.ZERO, new Vec2(16, 25)),
|
//size: new AABB(Vec2.ZERO, new Vec2(16, 25)),
|
||||||
exp: 100
|
exp: 100,
|
||||||
|
weapon : this.createWeapon("knife")
|
||||||
})
|
})
|
||||||
break;
|
break;
|
||||||
case "Snake": //Snake enemies drop from sky("trees")? or could just be very abundant
|
case "Snake": //Snake enemies drop from sky("trees")? or could just be very abundant
|
||||||
|
@ -736,11 +778,13 @@ export default class GameLevel extends Scene {
|
||||||
player: this.player,
|
player: this.player,
|
||||||
health: 50,
|
health: 50,
|
||||||
tilemap: "Main",
|
tilemap: "Main",
|
||||||
//actions:actions,
|
actions: actionsDefault,
|
||||||
|
status: statusArray,
|
||||||
goal: Statuses.REACHED_GOAL,
|
goal: Statuses.REACHED_GOAL,
|
||||||
size: new Vec2(16,16),
|
size: new Vec2(16,16),
|
||||||
offset : new Vec2(0, 16),
|
offset : new Vec2(0, 16),
|
||||||
exp: 50
|
exp: 50,
|
||||||
|
weapon : this.createWeapon("knife"),
|
||||||
})
|
})
|
||||||
break;
|
break;
|
||||||
case "Tiger": //Tiger can be miniboss for now?
|
case "Tiger": //Tiger can be miniboss for now?
|
||||||
|
@ -748,9 +792,11 @@ export default class GameLevel extends Scene {
|
||||||
player: this.player,
|
player: this.player,
|
||||||
health: 200,
|
health: 200,
|
||||||
tilemap: "Main",
|
tilemap: "Main",
|
||||||
//actions:actions,
|
|
||||||
goal: Statuses.REACHED_GOAL,
|
goal: Statuses.REACHED_GOAL,
|
||||||
exp: 100
|
exp: 100,
|
||||||
|
weapon : this.createWeapon("knife"),
|
||||||
|
actions: actionsDefault,
|
||||||
|
status: statusArray,
|
||||||
})
|
})
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -761,7 +807,10 @@ export default class GameLevel extends Scene {
|
||||||
tilemap: "Main",
|
tilemap: "Main",
|
||||||
//actions:actions,
|
//actions:actions,
|
||||||
goal: Statuses.REACHED_GOAL,
|
goal: Statuses.REACHED_GOAL,
|
||||||
exp: 50
|
exp: 50,
|
||||||
|
weapon : this.createWeapon("knife"),
|
||||||
|
actions: actionsDefault,
|
||||||
|
status: statusArray,
|
||||||
})
|
})
|
||||||
break;
|
break;
|
||||||
case "black_pudding":
|
case "black_pudding":
|
||||||
|
@ -774,7 +823,10 @@ export default class GameLevel extends Scene {
|
||||||
scale: .25,
|
scale: .25,
|
||||||
size: new Vec2(16,16),
|
size: new Vec2(16,16),
|
||||||
offset : new Vec2(0,0),
|
offset : new Vec2(0,0),
|
||||||
exp: 50
|
exp: 50,
|
||||||
|
weapon : this.createWeapon("knife"),
|
||||||
|
actions: actionsDefault,
|
||||||
|
status: statusArray,
|
||||||
})
|
})
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -831,6 +883,8 @@ export default class GameLevel extends Scene {
|
||||||
InputWrapper.enableInput();
|
InputWrapper.enableInput();
|
||||||
this.player.position.copy(this.startpos);
|
this.player.position.copy(this.startpos);
|
||||||
(<PlayerController>this.player._ai).CURRENT_HP = (<PlayerController>this.player._ai).MAX_HP + (<PlayerController>this.player._ai).CURRENT_BUFFS.hp;
|
(<PlayerController>this.player._ai).CURRENT_HP = (<PlayerController>this.player._ai).MAX_HP + (<PlayerController>this.player._ai).CURRENT_BUFFS.hp;
|
||||||
|
(<PlayerController>this.player._ai).lives --;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -848,6 +902,7 @@ export default class GameLevel extends Scene {
|
||||||
|
|
||||||
//TODO - decrease player health or can kill player here
|
//TODO - decrease player health or can kill player here
|
||||||
//(<PlayerController>this.player._ai).CURRENT_HP *= .75;
|
//(<PlayerController>this.player._ai).CURRENT_HP *= .75;
|
||||||
|
//this.emitter.fireEvent(Player_Events.PLAYER_KILLED);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
18
src/shattered_sword/Scenes/GameOver.ts
Normal file
18
src/shattered_sword/Scenes/GameOver.ts
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
import Vec2 from "../../Wolfie2D/DataTypes/Vec2";
|
||||||
|
import Input from "../../Wolfie2D/Input/Input";
|
||||||
|
import Label from "../../Wolfie2D/Nodes/UIElements/Label";
|
||||||
|
import { UIElementType } from "../../Wolfie2D/Nodes/UIElements/UIElementTypes";
|
||||||
|
import Scene from "../../Wolfie2D/Scene/Scene";
|
||||||
|
import Color from "../../Wolfie2D/Utils/Color";
|
||||||
|
|
||||||
|
export default class GameOver extends Scene {
|
||||||
|
|
||||||
|
startScene() {
|
||||||
|
const center = this.viewport.getCenter();
|
||||||
|
|
||||||
|
this.addUILayer("primary");
|
||||||
|
|
||||||
|
const gameOver = <Label>this.add.uiElement(UIElementType.LABEL, "primary", {position: new Vec2(center.x, center.y), text: "Game Over"});
|
||||||
|
gameOver.textColor = Color.WHITE;
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,7 +23,8 @@ export enum Statuses {
|
||||||
IN_RANGE = "IN_RANGE",
|
IN_RANGE = "IN_RANGE",
|
||||||
LOW_HEALTH = "LOW_HEALTH",
|
LOW_HEALTH = "LOW_HEALTH",
|
||||||
CAN_RETREAT = "CAN_RETREAT",
|
CAN_RETREAT = "CAN_RETREAT",
|
||||||
REACHED_GOAL = "GOAL"
|
REACHED_GOAL = "GOAL",
|
||||||
|
CAN_BERSERK = "CAN_BERSERK"
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum GameState {
|
export enum GameState {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user