Skip to content

Commit

Permalink
Merge pull request #1829 from gereon77/animate-place-orders
Browse files Browse the repository at this point in the history
Animate PlaceOrdersGameState
  • Loading branch information
gereon77 authored Mar 12, 2024
2 parents 6f390c2 + 67e07ee commit 8a293e8
Show file tree
Hide file tree
Showing 5 changed files with 349 additions and 95 deletions.
31 changes: 28 additions & 3 deletions agot-bg-game-server/src/client/MapComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -589,12 +589,14 @@ export default class MapComponent extends Component<MapComponentProps> {
let planningOrAction = (this.ingame.childGameState instanceof PlanningGameState || this.ingame.childGameState instanceof ActionGameState) ? this.ingame.childGameState : null;

if (planningOrAction instanceof ActionGameState && !(planningOrAction.childGameState instanceof UseRavenGameState)) {
// Do not show restricted orders after Raven state because Doran may cause a restricted order to be shown which still can be executed
// Do not highlight restricted orders after Raven state (during whole action phase)
// because abilities like Doran may cause an order to be shown as restricted suddenly though it isn't
planningOrAction = null;
}

const drawBorder = order?.type.restrictedTo == sea.kind;
const controller = drawBorder ? region.getController() : null;
const hasPlaceOrders = this.ingame.hasChildGameState(PlaceOrdersGameState);
const controller = drawBorder || hasPlaceOrders ? region.getController() : null;
const color = drawBorder && controller
? controller.id != "greyjoy"
? controller.color
Expand All @@ -604,6 +606,29 @@ export default class MapComponent extends Component<MapComponentProps> {
const wrap = properties.wrap;
const clickable = properties.onClick != undefined || wrap != undefined;

let placeAnimation = '';

if (hasPlaceOrders && controller) {
switch (controller.id) {
case "stark":
case "arryn":
placeAnimation = 'scale-in-top';
break;
case "targaryen":
case "baratheon":
placeAnimation = 'scale-in-right';
break;
case "martell":
case "tyrell":
placeAnimation = 'scale-in-bottom';
break;
case "greyjoy":
case "lannister":
placeAnimation = 'scale-in-left';
break;
}
}

return (
<ConditionalWrap condition={true}
key={`map-order_${region.id}`}
Expand Down Expand Up @@ -634,7 +659,7 @@ export default class MapComponent extends Component<MapComponentProps> {
id={`map-order-container_${region.id}`}
>
<div style={{ backgroundImage: `url(${backgroundUrl})`, borderColor: color }}
className={classNames("order-icon", {
className={classNames(`order-icon ${placeAnimation}`, {
"order-border": drawBorder,
"pulsate-bck": properties.animateAttention,
"pulsate-bck_fade-out": properties.animateFadeOut,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,11 @@ export default class PlayerMusteringComponent extends Component<GameStateCompone
</Col>
</Row>
</Col>
{this.isStarredConsolidatePowerMusteringType && this.musterings.size == 0 && (
<Col xs={12} className="text-center">
<small>Note: If you dont recruit any units, your order will be resolved to gain Power&nbsp;tokens.</small>
</Col>
)}
</>}
{(!this.doesControlCurrentHouse || this.props.gameState.ingame.isVassalHouse(this.house)) &&
<Col xs={12} className="text-center">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { observer } from "mobx-react";
import React, { Component, ReactNode } from "react";
import React, { Component, ReactElement, ReactNode } from "react";
import Region from "../../common/ingame-game-state/game-data-structure/Region";
import { observable } from "mobx";
import House from "../../common/ingame-game-state/game-data-structure/House";
import { Button } from "react-bootstrap";
import { Button, OverlayTrigger, Popover } from "react-bootstrap";
import GameStateComponentProps from "./GameStateComponentProps";
import Row from "react-bootstrap/Row";
import Col from "react-bootstrap/Col";
Expand Down Expand Up @@ -58,82 +58,18 @@ export default class ResolveSingleConsolidatePowerComponent extends Component<Ga
: <>House <b>{this.house.name}</b> must resolve one of its Consolidate&nbsp;Power{availableOrders.values.some(ot => ot instanceof IronBankOrderType) ? " or Iron\xa0Bank" : ""} orders.</>}
</Col>
{this.doesControlCurrentHouse ?
this.selectedOrderRegion && this.selectedOrderType ?
<>
<Col xs={12} className="text-center">
<p><b>{this.selectedOrderType.name}</b> in <b>{this.selectedOrderRegion.name}</b></p>
</Col>
<Col xs={12}>
<Row className="justify-content-center">
{this.selectedOrderType instanceof DefenseMusterOrderType && <>
<Col xs={12} className="d-flex justify-content-center">
<Button type="button" variant="success" onClick={() => {
this.gameState.chooseMustering(this.selectedOrderRegion as Region);
this.reset();
}}>
Muster in {this.selectedOrderRegion.name}
</Button>
</Col>
<Col xs={12} className="d-flex justify-content-center">
<Button type="button" variant="warning" onClick={() => {
this.gameState.chooseRemoveOrder(this.selectedOrderRegion as Region);
this.reset();
}}>
Ignore and remove order
</Button>
</Col>
</>}
{this.selectedOrderType instanceof ConsolidatePowerOrderType && <>
{this.selectedOrderType.starred && this.selectedOrderRegion.castleLevel > 0 &&
<Col xs="auto">
<Button type="button" variant="success" onClick={() => {
this.gameState.chooseMustering(this.selectedOrderRegion as Region);
this.reset();
}}>
Muster in {this.selectedOrderRegion.name}
</Button>
</Col>}
<Col xs="auto">
<Button type="button" onClick={() => {
this.gameState.chooseGainPowerTokens(this.selectedOrderRegion as Region);
this.reset();
}}>
{this.getPowerTokenButtonText(this.gameState.getPotentialGainedPowerTokens(this.selectedOrderRegion, this.house))}
</Button>
</Col>
</>}
{this.selectedOrderType instanceof IronBankOrderType && this.ironBank && <>
{this.ironBank.getPurchasableLoans(this.house).map(purchasable =>
<Col xs={12} className="d-flex justify-content-center" key={`loan-button-${purchasable.loan.id}`}>
<Button type="button" variant="success" onClick={() => {
this.gameState.choosePurchaseLoan(purchasable.slotIndex, this.selectedOrderRegion as Region);
this.reset();
}}>
Pay {purchasable.costs} Power token{purchasable.costs != 1 ? "s" : ""} to purchase {purchasable.loan.name}
</Button>
</Col>
)}
<Col xs={12} className="d-flex justify-content-center">
<Button type="button" variant="warning" onClick={() => {
this.gameState.chooseRemoveOrder(this.selectedOrderRegion as Region);
this.reset();
}}>
Ignore and remove order
</Button>
</Col>
</>}
<Col xs={12} className="d-flex justify-content-center">
<Button type="button"
variant="danger"
onClick={() => this.reset()}
>
Reset
</Button>
</Col>
</Row>
</Col>
</>
: <Col xs={12} className="text-center"><p>Click the order you want to resolve.</p></Col>
<>{this.selectedOrderRegion && this.selectedOrderType
? this.renderGameStateControls(this.selectedOrderRegion, this.selectedOrderType)
: <Col xs={12} className="text-center"><p>Click the order you want to resolve.</p></Col>}
<Col xs={12} className="d-flex justify-content-center">
<Button type="button"
variant="danger"
onClick={() => this.reset()}
>
Reset
</Button>
</Col>
</>
:
<Col xs={12} className="text-center">
Waiting for {this.gameState.ingame.getControllerOfHouse(this.house).house.name}...
Expand All @@ -142,22 +78,100 @@ export default class ResolveSingleConsolidatePowerComponent extends Component<Ga
);
}

private renderGameStateControls(orderRegion: Region, orderType: ConsolidatePowerOrderType | IronBankOrderType | DefenseMusterOrderType) {
return <>
<Col xs={12} className="text-center">
<p><b>{orderType.name}</b> in <b>{orderRegion.name}</b></p>
</Col>
<Col xs={12}>
<Row className="justify-content-center">
{orderType instanceof DefenseMusterOrderType && <>
<Col xs={12} className="d-flex justify-content-center">
<Button type="button" variant="success" onClick={() => {
this.gameState.chooseMustering(orderRegion as Region);
this.reset();
} }>
Muster in {orderRegion.name}
</Button>
</Col>
<Col xs={12} className="d-flex justify-content-center">
<Button type="button" variant="warning" onClick={() => {
this.gameState.chooseRemoveOrder(orderRegion as Region);
this.reset();
} }>
Ignore and remove order
</Button>
</Col>
</>}
{orderType instanceof ConsolidatePowerOrderType && <>
{orderType.starred && orderRegion.castleLevel > 0 &&
<Col xs="auto">
<Button type="button" variant="success" onClick={() => {
this.gameState.chooseMustering(orderRegion as Region);
this.reset();
} }>
Muster in {orderRegion.name}
</Button>
</Col>}
<Col xs="auto">
<Button type="button" onClick={() => {
this.gameState.chooseGainPowerTokens(orderRegion as Region);
this.reset();
} }>
{this.getPowerTokenButtonText(this.gameState.getPotentialGainedPowerTokens(orderRegion, this.house))}
</Button>
</Col>
</>}
{orderType instanceof IronBankOrderType && this.ironBank && <>
{this.ironBank.getPurchasableLoans(this.house).map(purchasable => <Col xs={12} className="d-flex justify-content-center" key={`loan-button-${purchasable.loan.id}`}>
<Button type="button" variant="success" onClick={() => {
this.gameState.choosePurchaseLoan(purchasable.slotIndex, orderRegion as Region);
this.reset();
} }>
Pay {purchasable.costs} Power token{purchasable.costs != 1 ? "s" : ""} to purchase {purchasable.loan.name}
</Button>
</Col>
)}
<Col xs={12} className="d-flex justify-content-center">
<Button type="button" variant="warning" onClick={() => {
this.gameState.chooseRemoveOrder(orderRegion as Region);
this.reset();
} }>
Ignore and remove order
</Button>
</Col>
</>}
</Row>
</Col>
</>;
}

private getPowerTokenButtonText(powerTokenCount: number): string {
return `Gain ${powerTokenCount} Power token${powerTokenCount != 1 ? "s" : ""}`;
}

private modifyOrdersOnMap(): [Region, PartialRecursive<OrderOnMapProperties>][] {
if (this.doesControlCurrentHouse) {
const availableOrders = this.gameState.parentGameState.getAvailableOrdersOfHouse(this.gameState.house);
if (this.selectedOrderRegion && this.selectedOrderType) {
availableOrders.clear();
availableOrders.set(this.selectedOrderRegion, this.selectedOrderType);
}
return availableOrders.entries.map(([r, ot]) => [
r,
{
highlight: { active: true },
onClick: () => this.onOrderClick(r, ot)
onClick: () => this.onOrderClick(r, ot),
wrap: (child: ReactElement) => (
<OverlayTrigger
placement="auto-start"
trigger="click"
rootClose
overlay={
<Popover id={"resolve-cp-order-popover_region_" + r.id} className="p-1">
{this.renderGameStateControls(r, ot)}
</Popover>
}
>
{child}
</OverlayTrigger>
)
}
]);
}
Expand All @@ -166,17 +180,18 @@ export default class ResolveSingleConsolidatePowerComponent extends Component<Ga
}

private onOrderClick(region: Region, orderType: ConsolidatePowerOrderType | IronBankOrderType | DefenseMusterOrderType): void {
if (!this.selectedOrderRegion) {
if (this.selectedOrderRegion == region) {
this.reset();
} else {
this.selectedOrderRegion = region;
this.selectedOrderType = orderType;
} else if (this.selectedOrderRegion == region) {
this.reset();
}
}

private reset(): void {
this.selectedOrderRegion = null;
this.selectedOrderType = null;
document.body.click();
}

componentDidMount(): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,16 @@ export default class SimpleChoiceComponent extends Component<GameStateComponentP
<Col xs={12} className="text-center">
{this.props.gameClient.doesControlHouse(this.props.gameState.house) ? (
<Row className="justify-content-center">
{this.props.gameState.choices.map((s, i) => (
<Col xs="auto" key={`simple-choice_${i}`}>
<Button type="button" onClick={() => this.choose(i)}>{s}</Button>
</Col>
))}
{this.props.gameState.choices.map((s, i) => {
const variant = s == "Ignore"
? "danger"
: s == "Activate"
? "success"
: undefined;
return <Col xs="auto" key={`simple-choice_${i}`}>
<Button type="button" variant={variant} onClick={() => this.choose(i)}>{s}</Button>
</Col>;
})}
</Row>
) : (
<>Waiting for {this.props.gameState.parentGameState.ingame.getControllerOfHouse(this.props.gameState.house).house.name}...</>
Expand Down
Loading

0 comments on commit 8a293e8

Please sign in to comment.