mirror of
https://github.com/Terncode/pixel.horse.git
synced 2026-09-24 21:55:52 +02:00
Archive update v0.53.2
This commit is contained in:
@@ -125,20 +125,20 @@ div(*ngIf="account")
|
||||
button.dropdown-item((click)="unmerge(m._id, m.data.account, m.data.merge)")
|
||||
| Split off #[b account]
|
||||
|
||||
h5 Support #[span.text-muted ({{support?.length || 0}})]
|
||||
table.table.table-sm(*ngIf="support?.length")
|
||||
thead
|
||||
tr
|
||||
th message
|
||||
th date
|
||||
tbody
|
||||
tr(*ngFor="let l of support")
|
||||
td
|
||||
fa-icon.mr-1([icon]="l.icon" [ngClass]="l.class")
|
||||
| {{l.message}}
|
||||
td
|
||||
time-field.mr-2([time]="l.date")
|
||||
span.text-muted ({{l.date | date:'MMM d'}})
|
||||
//- h5 Support #[span.text-muted ({{support?.length || 0}})]
|
||||
//- table.table.table-sm(*ngIf="support?.length")
|
||||
//- thead
|
||||
//- tr
|
||||
//- th message
|
||||
//- th date
|
||||
//- tbody
|
||||
//- tr(*ngFor="let l of support")
|
||||
//- td
|
||||
//- fa-icon.mr-1([icon]="l.icon" [ngClass]="l.class")
|
||||
//- | {{l.message}}
|
||||
//- td
|
||||
//- time-field.mr-2([time]="l.date")
|
||||
//- span.text-muted ({{l.date | date:'MMM d'}})
|
||||
|
||||
h5 Ban log #[span.text-muted ({{banLog?.length || 0}})]
|
||||
table.table.table-sm(*ngIf="banLog?.length")
|
||||
|
||||
@@ -38,9 +38,6 @@ ng-template(#duplicatesPopover)
|
||||
span.ml-3(title="Certificate expires in" [class.text-danger]="isOldCertificate")
|
||||
fa-icon.mr-2([icon]="certificateIcon")
|
||||
from-now([time]="status.certificateExpiration")
|
||||
span.ml-3(title="Last Patreon update" [class.text-danger]="isOldPatreon")
|
||||
fa-icon.mr-2([icon]="patreonIcon")
|
||||
from-now([time]="status.lastPatreonUpdate")
|
||||
|
||||
pagination(
|
||||
[totalItems]="filtered.length" [itemsPerPage]="itemsPerPage" [maxSize]="15" [(ngModel)]="currentPage"
|
||||
|
||||
@@ -12,32 +12,6 @@
|
||||
button.btn.btn-primary(type="button" (click)="saveFields()") Save
|
||||
button.btn.btn-default.ml-1(type="button" (click)="resetFields()") Reset
|
||||
|
||||
.col-6
|
||||
.form
|
||||
.form-group
|
||||
h3 Patreon
|
||||
.form-group.d-flex
|
||||
button.btn.btn-default((click)="updatePatreon()")
|
||||
| Update Data
|
||||
.input-group.ml-1(style="width: 400px")
|
||||
input.form-control(#patreonToken placeholder="patreon token")
|
||||
.input-group-append
|
||||
button.btn.btn-warning((click)="updatePatreonToken(patreonToken.value); patreonToken.value = ''")
|
||||
| Update Token
|
||||
.form-group
|
||||
| To get new token, got to #[a(href="https://www.patreon.com/portal/registration/register-clients") My Clients],
|
||||
| refresh token and update patreon token field with "Creator's Access Token" from the site.
|
||||
.form-group
|
||||
button.btn.btn-default((click)="getLastPatreonData()")
|
||||
| Get last patreon data
|
||||
|
||||
.form
|
||||
.form-group
|
||||
h3 Other
|
||||
.form-group
|
||||
button.btn.btn-default((click)="updatePastSupporters()")
|
||||
| Update past supporters
|
||||
|
||||
.row
|
||||
.col-12
|
||||
.form
|
||||
|
||||
@@ -85,17 +85,6 @@ ng-template(#alertModal)
|
||||
//-span.badge.badge-admin.badge-primary([title]="account.birthdate | date:'yyyy-MM-dd'")
|
||||
| {{age}}
|
||||
|
||||
span.badge.badge-admin.badge-supporter(
|
||||
*ngIf="isPatreonOrSupporter"
|
||||
[ngClass]="supporterClass"
|
||||
[class.declined]="account.supporterDeclinedSince && supporterLevel"
|
||||
[tooltip]="supporterTooltip")
|
||||
fa-icon([icon]="supporterIcon" [fixedWidth]="true")
|
||||
| {{supporterLevelString}}
|
||||
|
||||
span.badge.badge-admin.badge-supporter.badge-success(*ngIf="account.totalPledged" title="lifetime support")
|
||||
| ${{account.totalPledged}}
|
||||
|
||||
span.badge.badge-admin.badge-danger(*ngIf="account.ignoresCount" title="ignored by")
|
||||
| {{account.ignoresCount}}
|
||||
|
||||
|
||||
@@ -24,23 +24,23 @@ const accountDuplicates = new Map<string, DuplicatesInfo>();
|
||||
const predefinedAlerts = [
|
||||
{
|
||||
name: 'erp:flagged',
|
||||
message: `Your account has been flagged for inappropriate bahavior on PG rated server. `
|
||||
+ `Continuing that behavior may result in permanent ban.`
|
||||
message: `Your account has been flagged for inappropriate behavior on a PG rated server. `
|
||||
+ `Continuing that behavior may result in a permanent ban.`
|
||||
},
|
||||
{
|
||||
name: 'erp:timeout',
|
||||
message: `Your account has been timed out for inappropriate language and bahavior on PG rated server. `
|
||||
+ `Continuing that behavior may result in permanent ban.`
|
||||
message: `Your account has been timed out for inappropriate language and behavior on a PG rated server. `
|
||||
+ `Continuing that behavior may result in a permanent ban.`
|
||||
},
|
||||
{
|
||||
name: 'dups',
|
||||
message: `Your account has been flagged for making multiple accounts. `
|
||||
+ `Continuing that behavior may result in permanent ban.`
|
||||
+ `Continuing that behavior may result in a permanent ban.`
|
||||
},
|
||||
{
|
||||
name: 'under',
|
||||
message: `Your account has been reported for being underage, please do NOT play on 18+ server. `
|
||||
+ `Continuing that may result in permanent ban.`
|
||||
message: `Your account has been reported for being underage, please do NOT play on an 18+ server. `
|
||||
+ `Continuing that may result in a permanent ban.`
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
@@ -2,55 +2,13 @@ h1(focusTitle) About
|
||||
|
||||
.row.text-large
|
||||
.col-lg-7
|
||||
p.lead.
|
||||
A game of ponies building a town
|
||||
p.lead A Pony Town custom server
|
||||
|
||||
p This game is a derivative work based on #[a(href="https://pony.town") Pony Town]. The developers of Pony Town are not responsible for it in any way.
|
||||
|
||||
h2 Contact
|
||||
p For all inquiries please send an email to #[b {{contactEmail}}]
|
||||
|
||||
//- div
|
||||
hr
|
||||
|
||||
h2.text-success Custom servers
|
||||
|
||||
p.
|
||||
You can #[a.text-success(href="...") download the files] and start your own custom {{title}} server.
|
||||
p.
|
||||
The package contains server files and instruction on steps required to start your own server.
|
||||
It also allows you to customize and modify the game to your liking.
|
||||
p.
|
||||
Feel free to use this to host a server for your friends, fandom, language group or just a general
|
||||
server for everyone.
|
||||
|
||||
a.d-block.mx-auto.my-4.btn.btn-lg.btn-outline-success.px-3(href="..." style="max-width: 400px;")
|
||||
| Download game files
|
||||
|
||||
p.
|
||||
All necessary instructions required to build and run the server are included in README.md file
|
||||
included in the package.
|
||||
p.
|
||||
Running the server requires basic knowledge of configuring and hosting web applications,
|
||||
it's not intended for beginner users.
|
||||
|
||||
hr
|
||||
|
||||
div(*ngIf="patreonLink")
|
||||
h2 Support {{title}}
|
||||
|
||||
p.
|
||||
If you'd like to help keep {{title}} running, and support future development of the project,
|
||||
please consider #[a([href]="patreonLink" target="_blank" rel="noopener noreferrer") supporting us on Patreon].
|
||||
|
||||
support-button.d-block.mx-auto.my-4(style="max-width: 400px;")
|
||||
|
||||
p.
|
||||
Patreon supporter rewards include the following:
|
||||
ul
|
||||
li(*ngFor="let r of rewards")
|
||||
| {{r}}
|
||||
p.
|
||||
Note that in order to receive any patreon rewards you need to connect your Patreon to your {{title}} account.
|
||||
|
||||
h2 Technology
|
||||
|
||||
p.
|
||||
|
||||
@@ -77,41 +77,6 @@ h1(focusTitle) Account settings
|
||||
| Account removed successfully
|
||||
|
||||
.col-md-6
|
||||
div(style="margin-bottom: 100px;")
|
||||
.clearfix(*ngIf="showSupporter")
|
||||
.form-group
|
||||
h3
|
||||
fa-icon.mr-2([icon]="starIcon" [ngClass]="supporterClass")
|
||||
| Thank you for your support
|
||||
|
||||
supporter-pony.float-right(#pony (mouseenter)="pony.excite()" (mouseleave)="pony.reset()")
|
||||
|
||||
.form-group
|
||||
p Your reward tier: #[b {{supporterTitle}}]
|
||||
p Your rewards include:
|
||||
ul
|
||||
li(*ngFor="let r of supporterRewards")
|
||||
| {{r}}
|
||||
|
||||
p(*ngIf="supporter > 0")
|
||||
| Use <code>/ss hello</code> command to use supporter chat color.
|
||||
|
||||
p(*ngIf="supporter > 1")
|
||||
| Use <code>/s1 hello</code> and <code>/s2 hello</code> commands to use lower tier supporter chat colors.
|
||||
|
||||
.clearfix(*ngIf="showSupporterInfo")
|
||||
.form-group
|
||||
h3 Supporter info
|
||||
|
||||
supporter-pony.float-right(#pony (mouseenter)="pony.excite()" (mouseleave)="pony.reset()")
|
||||
|
||||
.form-group.text-muted
|
||||
p.
|
||||
You've successfully connected your Patreon account to Pony Town.
|
||||
If you support Pony Town on Patreon your supporter info will show up here.
|
||||
p.
|
||||
It should take no longer than 10 minutes to register your Patreon pledges.
|
||||
|
||||
div(style="margin-bottom: 100px;")
|
||||
.form-group
|
||||
.float-right
|
||||
|
||||
@@ -35,7 +35,7 @@ export const routes: Routes = [
|
||||
@NgModule({
|
||||
imports: [
|
||||
BrowserModule,
|
||||
RouterModule,
|
||||
RouterModule.forRoot(routes, { anchorScrolling: 'enabled' }),
|
||||
FormsModule,
|
||||
HttpClientModule,
|
||||
PopoverModule.forRoot(),
|
||||
|
||||
@@ -37,13 +37,11 @@
|
||||
.text-right
|
||||
.d-flex.flex-wrap
|
||||
//- .text-nowrap.mr-2
|
||||
| © 2016-{{date | date:'yyyy'}}
|
||||
| © 2019-{{date | date:'yyyy'}}
|
||||
| #[a.text-muted.mr-1([href]="twitterLink" target="_blank") {{copyright}}] |
|
||||
.text-nowrap
|
||||
a.text-muted.mr-2(*ngIf="twitterLink" [href]="twitterLink" target="_blank" title="Twitter")
|
||||
fa-icon([icon]="twitterIcon" [fixedWidth]="true")
|
||||
a.text-muted.mr-2(*ngIf="patreonLink" [href]="patreonLink" target="_blank" title="Patreon")
|
||||
fa-icon([icon]="patreonIcon" [fixedWidth]="true")
|
||||
a.text-muted.mr-2(*ngIf="contactEmail" href="mailto:{{contactEmail}}" target="_blank" title="Email")
|
||||
fa-icon([icon]="emailIcon" [fixedWidth]="true")
|
||||
div
|
||||
|
||||
@@ -119,18 +119,21 @@ $chat-pad: 5px;
|
||||
position: fixed;
|
||||
top: 5px;
|
||||
right: 5px;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
#friends-box {
|
||||
position: fixed;
|
||||
top: 5px;
|
||||
right: 45px;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
#swap-box {
|
||||
position: fixed;
|
||||
top: 5px;
|
||||
right: 86px;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
#notifications {
|
||||
|
||||
@@ -8,8 +8,7 @@ import { GameService } from '../services/gameService';
|
||||
import { Model, Friend } from '../services/model';
|
||||
import { version, host, contactEmail, supporterLink, twitterLink, copyrightName } from '../../client/data';
|
||||
import { PonyTownGame } from '../../client/game';
|
||||
import { faTwitter, faPatreon, faEnvelope, faCog, faHome, faGamepad, faInfoCircle, faHorseHead } from '../../client/icons';
|
||||
import { InstallService } from '../services/installService';
|
||||
import { faTwitter, faPatreon, faEnvelope, faCog, faHome, faInfoCircle, faHorseHead, faQuestionCircle } from '../../client/icons';
|
||||
import { OAuthProvider, Entity, FakeEntity, Pony } from '../../common/interfaces';
|
||||
import { registerServiceWorker, isBrowserOutdated, checkIframeKey } from '../../client/clientUtils';
|
||||
import { ErrorReporter } from '../services/errorReporter';
|
||||
@@ -49,7 +48,7 @@ export class App implements OnInit, OnDestroy {
|
||||
readonly patreonIcon = faPatreon;
|
||||
readonly cogIcon = faCog;
|
||||
readonly homeIcon = faHome;
|
||||
readonly helpIcon = faGamepad;
|
||||
readonly helpIcon = faQuestionCircle;
|
||||
readonly aboutIcon = faInfoCircle;
|
||||
readonly charactersIcon = faHorseHead;
|
||||
readonly contactEmail = contactEmail;
|
||||
@@ -67,12 +66,11 @@ export class App implements OnInit, OnDestroy {
|
||||
private game: PonyTownGame,
|
||||
private router: Router,
|
||||
private activatedRoute: ActivatedRoute,
|
||||
private installService: InstallService,
|
||||
private errorReporter: ErrorReporter,
|
||||
) {
|
||||
}
|
||||
get canInstall() {
|
||||
return this.installService.canInstall;
|
||||
return false;
|
||||
}
|
||||
get loading() {
|
||||
return this.model.loading;
|
||||
|
||||
@@ -13,8 +13,7 @@ page-loader(*ngIf="!playing")
|
||||
h1.sr-only(focusTitle) Characters
|
||||
h2.sr-only Character selection
|
||||
.mx-auto(style="max-width: 400px;")
|
||||
support-button.mb-3
|
||||
install-button.mb-3
|
||||
visit-pt-button.mb-3
|
||||
character-select(
|
||||
[(error)]="error" [newButton]="true" [removeButton]="true" (change)="updateMuzzles()"
|
||||
(preview)="previewPony = $event")
|
||||
|
||||
@@ -5,7 +5,9 @@ h1(focusTitle) Help
|
||||
|
||||
section
|
||||
h2 Contact
|
||||
p For all inquiries please send an email to #[b {{contactEmail}}]
|
||||
p.
|
||||
For technical issues, see the #[a(routerLink="/help" fragment="issues") Common Issues] section. If it doesn't solve your problem,
|
||||
send an email to #[b {{contactEmail}}].
|
||||
|
||||
section
|
||||
h2 Controls
|
||||
@@ -152,15 +154,6 @@ h1(focusTitle) Help
|
||||
li <code>/removetoolbox</code> - removes toolbox from the house (need to be alone in the house or a party leader)
|
||||
li <code>/restoretoolbox</code> - restores toolbox to the house (need to be alone in the house or a party leader)
|
||||
|
||||
section
|
||||
h4 Supporter-only commands
|
||||
|
||||
ul.spaced-list
|
||||
li <code>/ss</code> - supporter colored text
|
||||
li <code>/s1</code> - tier 1 supporter colored text (for use by higher tier supporters)
|
||||
li <code>/s2</code> - tier 2 supporter colored text (for use by higher tier supporters)
|
||||
li <code>/s3</code> - tier 3 supporter colored text (for use by higher tier supporters)
|
||||
|
||||
section
|
||||
h2 Chat emojis
|
||||
p.
|
||||
@@ -176,7 +169,7 @@ h1(focusTitle) Help
|
||||
|
||||
.col-md-5
|
||||
section
|
||||
h2 Common issues
|
||||
h2#issues Common issues
|
||||
|
||||
section
|
||||
h4 Keys stuck when using iPad keyboard
|
||||
@@ -247,13 +240,13 @@ h1(focusTitle) Help
|
||||
using #[b Chrome] or #[b Edge] browsers for best performance.
|
||||
|
||||
section
|
||||
h4 Why can't I create multiple accounts
|
||||
h4#rules Why can't I create multiple accounts
|
||||
p.text-fading.
|
||||
This restriction is in-place to protect you and the game itself from other players in the game.
|
||||
This restriction is in place to protect you and the game itself from other players in the game.
|
||||
p.text-fading.
|
||||
Allowing multiple accounts for single person invalidates ignore and hide systems that
|
||||
allow you to ignore and hide other players that are harassing or bothering you in any way.
|
||||
It also invalidates mute and ban system that is in-place to protect you from players breaking
|
||||
It also invalidates mute and ban system that is in place to protect you from players breaking
|
||||
the game rules to bother or harass others.
|
||||
p.text-fading.
|
||||
Allowing use of multiple accounts at the same time would dramatically increase load on the
|
||||
@@ -263,13 +256,13 @@ h1(focusTitle) Help
|
||||
game anymore.
|
||||
p.text-fading.
|
||||
Use of multiple accounts also invalidates any limits (like character limit) that we put on the accounts.
|
||||
The limits are in-place to prevent large amount of players that we have at the moment from
|
||||
The limits are in place to prevent large amount of players that we have at the moment from
|
||||
exhausting our limited server resources.
|
||||
|
||||
section
|
||||
h4 Why can't I modify the game with hacks or scripts
|
||||
p.text-fading.
|
||||
This restriction is in-place to protect you and the game itself from other players in the game.
|
||||
This restriction is in place to protect you and the game itself from other players in the game.
|
||||
p.text-fading.
|
||||
Almost all third-party scripts used in-game were used to harass other players. Even when the
|
||||
creator of the script did not intend it to be used in that way, the limited knowledge of the
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Component } from '@angular/core';
|
||||
import { emojis } from '../../../client/emoji';
|
||||
import { faArrowLeft, faArrowRight, faArrowUp, faArrowDown } from '../../../client/icons';
|
||||
import { contactEmail } from '../../../client/data';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
selector: 'help',
|
||||
@@ -16,4 +17,15 @@ export class Help {
|
||||
readonly emotes = emojis.map(e => e.names[0]);
|
||||
readonly mac = /Macintosh/.test(navigator.userAgent);
|
||||
readonly contactEmail = contactEmail;
|
||||
|
||||
// allow scrolling to #issues and #rules fragments
|
||||
|
||||
constructor(private route: ActivatedRoute) {}
|
||||
|
||||
ngAfterViewInit() {
|
||||
this.route.fragment.subscribe(f => {
|
||||
const element = document.querySelector("#" + f);
|
||||
if (element) setTimeout(() => element.scrollIntoView(), 10);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
div(*ngIf="!playing")
|
||||
.text-center.heading
|
||||
img.pixelart.home-logo(revSrc="images/logo-large.png" alt="Pony Town")
|
||||
img.pixelart.home-logo(revSrc="images/logo-large.png" alt="Pony Town Custom Server")
|
||||
|
||||
.mx-auto.home-content
|
||||
page-loader
|
||||
@@ -19,13 +19,13 @@ div(*ngIf="!playing")
|
||||
|
||||
div(*ngIf="!!account")
|
||||
.form-group
|
||||
support-button
|
||||
visit-pt-button
|
||||
.form-group(*ngIf="canInstall")
|
||||
install-button
|
||||
.form-group
|
||||
character-select([(error)]="error" [editButton]="true" (preview)="previewPony = $event")
|
||||
.form-group
|
||||
character-preview([pony]="previewInfo" [state]="state" [passive]="true" [name]="previewName" [tag]="previewTag")
|
||||
character-preview([pony]="previewInfo" [state]="state" [passive]="false" [name]="previewName" [tag]="previewTag")
|
||||
.form-group.text-center
|
||||
play-box([(error)]="error")
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ import { Component } from '@angular/core';
|
||||
import { Model, getPonyTag } from '../../services/model';
|
||||
import { defaultPonyState } from '../../../client/ponyHelpers';
|
||||
import { GameService } from '../../services/gameService';
|
||||
import { InstallService } from '../../services/installService';
|
||||
import { OAuthProvider, PonyObject } from '../../../common/interfaces';
|
||||
import { stand } from '../../../client/ponyAnimations';
|
||||
|
||||
@Component({
|
||||
selector: 'home',
|
||||
@@ -14,10 +14,11 @@ export class Home {
|
||||
state = defaultPonyState();
|
||||
previewPony: PonyObject | undefined = undefined;
|
||||
error?: string;
|
||||
private animationTime = 0;
|
||||
private interval?: any;
|
||||
constructor(
|
||||
private gameService: GameService,
|
||||
private model: Model,
|
||||
private installService: InstallService,
|
||||
) {
|
||||
}
|
||||
get authError() {
|
||||
@@ -27,7 +28,7 @@ export class Home {
|
||||
return this.model.accountAlert;
|
||||
}
|
||||
get canInstall() {
|
||||
return this.installService.canInstall;
|
||||
return false;
|
||||
}
|
||||
get playing() {
|
||||
return this.gameService.playing;
|
||||
@@ -53,4 +54,21 @@ export class Home {
|
||||
signIn(provider: OAuthProvider) {
|
||||
this.model.signIn(provider);
|
||||
}
|
||||
ngOnInit() {
|
||||
let last = Date.now();
|
||||
this.interval = setInterval(() => {
|
||||
const now = Date.now();
|
||||
this.update((now - last) / 1000);
|
||||
last = now;
|
||||
}, 1000 / 24);
|
||||
}
|
||||
ngOnDestroy() {
|
||||
clearInterval(this.interval);
|
||||
}
|
||||
update(delta: number) {
|
||||
this.animationTime += delta;
|
||||
const animation = stand;
|
||||
this.state.animation = animation;
|
||||
this.state.animationFrame = Math.floor(this.animationTime * animation.fps) % animation.frames.length;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -569,7 +569,7 @@ export class AdminModel {
|
||||
const count = this.events.reduce((sum, e) => sum + (e.deleted ? 0 : 1), 0);
|
||||
const inred = this.events.reduce((sum, e) => sum + ((!e.deleted && e.count > 9) ? 1 : 0), 0);
|
||||
const flag = this.isLowDiskSpace || this.isLowMemory || this.isOldCertificate || this.isOldPatreon;
|
||||
document.title = `${ponies} | ${count}${repeat('!', inred)}${flag ? ' 🚩' : ''}${!this.connected ? ' ⚠' : ''} | Pony Town`;
|
||||
document.title = `${ponies} | ${count}${repeat('!', inred)}${flag ? ' 🚩' : ''}${!this.connected ? ' ⚠' : ''} | Your Town`;
|
||||
}
|
||||
private notify(title: string, body: string) {
|
||||
if (this.notifications && notification.permission === 'granted') {
|
||||
|
||||
@@ -20,7 +20,7 @@ export class InstallService {
|
||||
}
|
||||
}
|
||||
get canInstall() {
|
||||
return !!this.installEvent || (DEVELOPMENT && localStorage.getItem('install'));
|
||||
return false;
|
||||
}
|
||||
install() {
|
||||
if (!this.installEvent) {
|
||||
|
||||
@@ -22,7 +22,7 @@ import { ErrorReporter } from './errorReporter';
|
||||
import { randomString } from '../../common/stringUtils';
|
||||
import { StorageService } from './storageService';
|
||||
import { decompressPonyString, compressPonyString, decodePonyInfo } from '../../common/compressPony';
|
||||
import { SECOND, PLAYER_DESC_MAX_LENGTH } from '../../common/constants';
|
||||
import { SECOND, PLAYER_DESC_MAX_LENGTH, NEW_ACCOUNT_PONY_NAME } from '../../common/constants';
|
||||
import { canUseTag } from '../../common/tags';
|
||||
|
||||
export interface Friend extends FriendData {
|
||||
@@ -191,7 +191,11 @@ export class Model {
|
||||
this.ponies = account.ponies ? account.ponies.sort(comparePonies) : [];
|
||||
this.friends = undefined;
|
||||
|
||||
this.selectPony(getDefaultPony(this.ponies));
|
||||
let defaultPony = getDefaultPony(this.ponies);
|
||||
if (this.ponies.length === 0) {
|
||||
defaultPony.name = NEW_ACCOUNT_PONY_NAME;
|
||||
}
|
||||
this.selectPony(defaultPony);
|
||||
this.storage.setItem('vid', account.id);
|
||||
this.loading = false;
|
||||
this.accountAlert = account.alert;
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
ng-template(#actionsModal)
|
||||
actions-modal((close)="closeActions()" [focusTrap]="true" (keydown)="$event.stopPropagation()")
|
||||
|
||||
.action-bar(
|
||||
[class.has-scroller]="hasScroller" [class.is-mobile]="mobile" [class.is-blurred]="blurred"
|
||||
#scroller (mousewheel)="scroll($event)" (wheel)="scroll($event)" (scroll)="true")
|
||||
@@ -14,6 +17,8 @@
|
||||
[draggablePad]="10"
|
||||
(draggableDrag)="drag(i)"
|
||||
(draggableDrop)="drop($event, i)")
|
||||
button.action-settings.game-button((click)="openActions()" style="touch-action: inherit;")
|
||||
fa-icon.action-icon([icon]="cogIcon" [fixedWidth]="true")
|
||||
.action-button-padding
|
||||
.scroller-label
|
||||
| scroll using this bar
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
.action-bar {
|
||||
overflow: hidden;
|
||||
padding-bottom: 7px;
|
||||
padding-bottom: 0px;
|
||||
padding-top: 7px;
|
||||
padding-right: 5px;
|
||||
max-width: calc(100vw - 50px);
|
||||
@@ -60,7 +60,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
action-button {
|
||||
.action-icon {
|
||||
font-size: 30px;
|
||||
position: relative;
|
||||
right: 6px;
|
||||
bottom: 8px;
|
||||
}
|
||||
|
||||
action-button, .action-settings {
|
||||
pointer-events: auto;
|
||||
margin: 3px 6px;
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Component, Input, ViewChild, ElementRef } from '@angular/core';
|
||||
import { BsModalService, BsModalRef } from 'ngx-bootstrap/modal';
|
||||
import { ButtonAction } from '../../../common/interfaces';
|
||||
import { PonyTownGame } from '../../../client/game';
|
||||
import { isMobile } from '../../../client/data';
|
||||
@@ -6,6 +7,7 @@ import { useAction, serializeActions } from '../../../client/buttonActions';
|
||||
import { SettingsService } from '../../services/settingsService';
|
||||
import { ACTIONS_LIMIT } from '../../../common/constants';
|
||||
import { last } from '../../../common/utils';
|
||||
import { faCog } from '../../../client/icons';
|
||||
|
||||
@Component({
|
||||
selector: 'action-bar',
|
||||
@@ -14,11 +16,14 @@ import { last } from '../../../common/utils';
|
||||
})
|
||||
export class ActionBar {
|
||||
@ViewChild('scroller', { static: true }) scroller!: ElementRef;
|
||||
@ViewChild('actionsModal', { static: true }) actionsModal!: ElementRef;
|
||||
@Input() blurred = false;
|
||||
readonly cogIcon = faCog;
|
||||
activeAction: ButtonAction | undefined = undefined;
|
||||
shortcuts = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '='];
|
||||
private modalRef?: BsModalRef;
|
||||
private _editable = false;
|
||||
constructor(private game: PonyTownGame, private settings: SettingsService) {
|
||||
constructor(private game: PonyTownGame, private settings: SettingsService, private modalService: BsModalService) {
|
||||
}
|
||||
@Input() get editable() {
|
||||
return this._editable;
|
||||
@@ -68,6 +73,20 @@ export class ActionBar {
|
||||
this.scroller.nativeElement.scrollLeft += delta * 20;
|
||||
}
|
||||
}
|
||||
openActions() {
|
||||
if (this.modalRef) {
|
||||
this.closeActions();
|
||||
}
|
||||
else {
|
||||
this.modalRef = this.modalService.show(this.actionsModal, { ignoreBackdropClick: true });
|
||||
}
|
||||
}
|
||||
closeActions() {
|
||||
if (this.modalRef) {
|
||||
this.modalRef.hide();
|
||||
this.modalRef = undefined;
|
||||
}
|
||||
}
|
||||
private updateFreeSlots() {
|
||||
const actions = this.actions;
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import { element, textNode, removeAllNodes, replaceNodes } from '../../../client
|
||||
import { DEFAULT_CHATLOG_OPACITY, PONY_TYPE } from '../../../common/constants';
|
||||
import { faCaretUp, faArrowDown } from '../../../client/icons';
|
||||
import { sampleMessages } from '../../../common/debugData';
|
||||
import { isMobile } from '../../../client/data';
|
||||
|
||||
interface IndexEntryUser {
|
||||
id: number;
|
||||
@@ -354,7 +355,10 @@ export class ChatLog implements AfterViewInit, OnDestroy, DoCheck {
|
||||
return (tab === 'local' || tab === 'party' || tab === 'whisper') ? tab : 'local';
|
||||
}
|
||||
get open() {
|
||||
return !this.settings.chatlogClosed;
|
||||
if (this.settings.chatlogClosed === undefined) {
|
||||
return !isMobile; // closed by default on mobile
|
||||
}
|
||||
return this.settings.chatlogClosed === false;
|
||||
}
|
||||
get width() {
|
||||
return this.settings.chatlogWidth || 500;
|
||||
@@ -475,7 +479,7 @@ export class ChatLog implements AfterViewInit, OnDestroy, DoCheck {
|
||||
}
|
||||
}
|
||||
toggle() {
|
||||
this.settings.chatlogClosed = !this.settings.chatlogClosed;
|
||||
this.settings.chatlogClosed = this.open;
|
||||
this.settingsService.saveBrowserSettings();
|
||||
this.updateOpen();
|
||||
}
|
||||
|
||||
@@ -35,7 +35,6 @@ $color-picker-box-offset: 5px;
|
||||
border: solid 1px $border-color;
|
||||
border-radius: 2px;
|
||||
pointer-events: none;
|
||||
z-index: 10;
|
||||
|
||||
.disabled > & {
|
||||
opacity: 0.8;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.btn-group.d-flex(*ngIf="canInstall")
|
||||
button.btn.btn-lg.btn-outline-success.text-wrap.flex-grow-1((click)="install()")
|
||||
| Add #[b Pony Town] to {{isMobile ? 'home screen' : 'desktop'}}
|
||||
| Add #[b Pony Town Custom Server] to {{isMobile ? 'home screen' : 'desktop'}}
|
||||
button.btn.btn-lg.btn-outline-success.flex-grow-0(
|
||||
(click)="dismiss()" title="Dismiss" [attr.aria-label]="'Dismiss add to ' + (isMobile ? 'home screen' : 'desktop')")
|
||||
fa-icon([icon]="closeIcon")
|
||||
|
||||
@@ -13,7 +13,7 @@ export class InstallButton {
|
||||
constructor(private installService: InstallService) {
|
||||
}
|
||||
get canInstall() {
|
||||
return this.installService.canInstall;
|
||||
return false;
|
||||
}
|
||||
get isMobile() {
|
||||
return isMobile;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
nav.navbar.navbar-expand.justify-content-end(role="navigation")
|
||||
.d-none.d-md-block
|
||||
a.pixelart.logo(*ngIf="logo" routerLink="/" routerLinkActive="active" [routerLinkActiveOptions]="{ exact: true }")
|
||||
img.pixelart.logo-large(revSrc="images/logo-large.png" alt="Pony Town" width="287" height="65")
|
||||
img.pixelart.logo-small(revSrc="images/logo-small.png" alt="Pony Town" width="37" height="43")
|
||||
img.pixelart.logo-large(revSrc="images/logo-large.png" alt="Pony Town Custom Server" width="287" height="88")
|
||||
img.pixelart.logo-small(revSrc="images/logo-small.png" alt="Pony Town Custom Server" width="37" height="43")
|
||||
|
||||
.navbar-collapse.text-right
|
||||
.navbar-nav.ml-auto
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
.form-group(*ngIf="isAndroidBrowser")
|
||||
.alert.alert-warning(role="alert")
|
||||
| Your browser is outdated and is not able to correctly run Pony Town.
|
||||
| Your browser is outdated and is not able to correctly run Pony Town Custom Server.
|
||||
| Please install different browser to be able to play the game.
|
||||
|
||||
.form-group(*ngIf="model.missingBirthdate && !birthdateSet && requestBirthdate")
|
||||
@@ -86,8 +86,8 @@
|
||||
.form-group(*ngIf="isBrowserOutdated")
|
||||
.alert.alert-warning(role="alert")
|
||||
button.close.float-right((click)="dismissOutdatedBrowser()" aria-label="Close" style="font-size: 20px;") ×
|
||||
| Your browser is outdated and is known to have issues running Pony Town.
|
||||
| Make sure you have latest version installed.
|
||||
| Your browser is outdated and is known to have issues running Pony Town Custom Server.
|
||||
| Make sure you have the latest version installed.
|
||||
|
||||
.form-group(*ngIf="invalidVersion && !offline")
|
||||
.alert.alert-danger(role="alert")
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
h5 General rules
|
||||
ul.text-muted.list-rules
|
||||
li(*ngFor="let r of rules") {{r}}
|
||||
p.text-muted For more details about the rules, see our #[a(routerLink="/help" fragment="rules") Help page].
|
||||
hr
|
||||
|
||||
h5 Notice
|
||||
h5 This is a Pony Town custom server
|
||||
p.text-muted
|
||||
| This game is very #[strong early in development]. There might be bugs and occasional downtimes.
|
||||
| The developers of Pony Town are not responsible for this server or the contents on it in any way.
|
||||
p.text-muted
|
||||
| Please do not redistribute any of the game files or code.
|
||||
| You can check out the original game #[a(href="https://pony.town") here].
|
||||
|
||||
@@ -12,32 +12,33 @@ ng-template(#actionsModal)
|
||||
button.game-button.dropdown-toggle.no-arrow(dropdownToggle (click)="false" title="Settings")
|
||||
fa-icon([icon]="cogIcon" [fixedWidth]="true")
|
||||
.dropdown-menu.dropdown-menu-right.settings-box-menu(*dropdownMenu)
|
||||
.dropdown-header.d-flex.justify-content-between
|
||||
.dropdown-header.d-flex.justify-content-between.mb-1
|
||||
span {{server}}
|
||||
span.clock-display {{time}}
|
||||
.dropdown-item.d-flex
|
||||
.dropdown-item.d-flex.mb-1
|
||||
fa-icon.mr-2([icon]="searchIcon" [fixedWidth]="true")
|
||||
.flex-grow-1 Scale (x{{scale}})
|
||||
button.btn.btn-xs.btn-outline-secondary((click)="zoomOut()" aria-label="Zoom out")
|
||||
fa-icon([icon]="minusIcon" [fixedWidth]="true")
|
||||
button.btn.btn-xs.btn-outline-secondary.ml-2((click)="zoomIn()" aria-label="Zoom in")
|
||||
fa-icon([icon]="plusIcon" [fixedWidth]="true")
|
||||
.dropdown-item.dropdown-item-static
|
||||
.dropdown-item.dropdown-item-static.mb-1
|
||||
a((click)="toggleVolume()" title="Toggle sound")
|
||||
fa-icon([icon]="volumeIcon" [fixedWidth]="true")
|
||||
//.flex-grow-1 Volume
|
||||
slider-bar([(value)]="volume" [step]="1" (started)="volumeStarted()")
|
||||
.text-muted.text-right(*ngIf="track" style="margin-top: -5px;")
|
||||
small
|
||||
| playing: #[b {{track}}]
|
||||
a.text-muted.ml-1((click)="nextTrack()" title="Next track")
|
||||
fa-icon([icon]="forwardIcon" [fixedWidth]="true")
|
||||
a.dropdown-item((click)="unhideAllHiddenPlayers()")
|
||||
a.dropdown-item((click)="unhideAllHiddenPlayers()").mb-1
|
||||
fa-icon.mr-2([icon]="emptyIcon" [fixedWidth]="true")
|
||||
| Unhide players (temporary)
|
||||
a.dropdown-item((click)="openSettings()")
|
||||
a.dropdown-item((click)="openSettings()").mb-1
|
||||
fa-icon.mr-2([icon]="emptyIcon" [fixedWidth]="true")
|
||||
| Settings
|
||||
a.dropdown-item((click)="openActions()")
|
||||
a.dropdown-item((click)="openActions()").mb-1
|
||||
fa-icon.mr-2([icon]="emptyIcon" [fixedWidth]="true")
|
||||
| Actions
|
||||
//-a.dropdown-item((click)="openInvites()" *ngIf="hasInvites")
|
||||
|
||||
@@ -30,14 +30,12 @@
|
||||
tab(title="Graphics" [icon]="graphicsIcon")
|
||||
div(*tabContent)
|
||||
.form-group
|
||||
custom-checkbox(
|
||||
*ngIf="!lockLowGraphicsMode" [(checked)]="browser.lowGraphicsMode"
|
||||
help="Can improve game performance in some cases")
|
||||
| Low graphics mode
|
||||
custom-checkbox(
|
||||
*ngIf="lockLowGraphicsMode" [checked]="true" [disabled]="true"
|
||||
help="Can improve game performance in some cases")
|
||||
| Low graphics mode
|
||||
label#graphics-quality-label Graphics quality
|
||||
div
|
||||
slider-bar.mr-2.mb-2(
|
||||
[(value)]="browser.graphicsQuality" [min]="0" [max]="maxGraphicsQuality" [step]="1"
|
||||
style="max-width: 300px" labelledBy="graphics-quality-label")
|
||||
| {{graphicsQualityText}}
|
||||
.form-group
|
||||
custom-checkbox(
|
||||
[(checked)]="browser.brightNight"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Component, Output, EventEmitter, OnInit, OnDestroy } from '@angular/core';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { AccountSettings, BrowserSettings } from '../../../common/interfaces';
|
||||
import { AccountSettings, BrowserSettings, GraphicsQuality } from '../../../common/interfaces';
|
||||
import { SettingsService } from '../../services/settingsService';
|
||||
import {
|
||||
DEFAULT_CHATLOG_OPACITY, MAX_CHATLOG_RANGE, MIN_CHATLOG_RANGE, isChatlogRangeUnlimited, MAX_FILTER_WORDS_LENGTH
|
||||
@@ -9,7 +9,7 @@ import { StorageService } from '../../services/storageService';
|
||||
import { cloneDeep } from '../../../common/utils';
|
||||
import { PonyTownGame } from '../../../client/game';
|
||||
import { updateRangeIndicator, readFileAsText } from '../../../client/clientUtils';
|
||||
import { faSlidersH, faCommentSlash, faGamepad, faImage, faDownload, faUpload } from '../../../client/icons';
|
||||
import { faSlidersH, faCommentSlash, faGamepad, faImage, faDownload, faUpload, faComment } from '../../../client/icons';
|
||||
|
||||
@Component({
|
||||
selector: 'settings-modal',
|
||||
@@ -19,8 +19,10 @@ import { faSlidersH, faCommentSlash, faGamepad, faImage, faDownload, faUpload }
|
||||
export class SettingsModal implements OnInit, OnDestroy {
|
||||
readonly maxChatlogRange = MAX_CHATLOG_RANGE;
|
||||
readonly minChatlogRange = MIN_CHATLOG_RANGE;
|
||||
readonly maxGraphicsQuality: number;
|
||||
readonly maxGraphicsQualityValue: GraphicsQuality;
|
||||
readonly gameIcon = faSlidersH;
|
||||
readonly chatIcon = faCommentSlash;
|
||||
readonly chatIcon = faComment;
|
||||
readonly filtersIcon = faCommentSlash;
|
||||
readonly controlsIcon = faGamepad;
|
||||
readonly graphicsIcon = faImage;
|
||||
@@ -38,6 +40,24 @@ export class SettingsModal implements OnInit, OnDestroy {
|
||||
private storage: StorageService,
|
||||
private game: PonyTownGame,
|
||||
) {
|
||||
if (game.webgl) {
|
||||
if (game.webgl.failedFBO) {
|
||||
this.maxGraphicsQuality = 0;
|
||||
this.maxGraphicsQualityValue = GraphicsQuality.Low;
|
||||
}
|
||||
else if (game.webgl.failedDepthBuffer) {
|
||||
this.maxGraphicsQuality = 1;
|
||||
this.maxGraphicsQualityValue = GraphicsQuality.Medium;
|
||||
}
|
||||
else {
|
||||
this.maxGraphicsQuality = 2;
|
||||
this.maxGraphicsQualityValue = GraphicsQuality.High;
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.maxGraphicsQuality = 2;
|
||||
this.maxGraphicsQualityValue = GraphicsQuality.High;
|
||||
}
|
||||
}
|
||||
get pane() {
|
||||
return this.storage.getItem('settings-modal-pane') || 'game';
|
||||
@@ -45,13 +65,25 @@ export class SettingsModal implements OnInit, OnDestroy {
|
||||
set pane(value: string) {
|
||||
this.storage.setItem('settings-modal-pane', value);
|
||||
}
|
||||
get lockLowGraphicsMode() {
|
||||
return this.game.failedFBO;
|
||||
}
|
||||
get chatlogRangeText() {
|
||||
const range = this.account.chatlogRange;
|
||||
return isChatlogRangeUnlimited(range) ? 'entire screen' : `${range} tiles`;
|
||||
}
|
||||
get graphicsQualityText() {
|
||||
if (!this.game.webgl || (this.browser.graphicsQuality === undefined)) {
|
||||
return 'Undefined';
|
||||
}
|
||||
|
||||
if (this.game.webgl.failedFBO || (this.browser.graphicsQuality === GraphicsQuality.Low)) {
|
||||
return 'Low';
|
||||
}
|
||||
else if (this.game.webgl.failedDepthBuffer || (this.browser.graphicsQuality === GraphicsQuality.Medium)) {
|
||||
return 'Medium';
|
||||
}
|
||||
else {
|
||||
return 'High';
|
||||
}
|
||||
}
|
||||
ngOnInit() {
|
||||
this.accountBackup = cloneDeep(this.settingsService.account);
|
||||
this.browserBackup = cloneDeep(this.settingsService.browser);
|
||||
@@ -120,6 +152,10 @@ export class SettingsModal implements OnInit, OnDestroy {
|
||||
if (this.account.filterWords === undefined) {
|
||||
this.account.filterWords = '';
|
||||
}
|
||||
|
||||
if (this.browser.graphicsQuality === undefined) {
|
||||
this.browser.graphicsQuality = this.maxGraphicsQualityValue;
|
||||
}
|
||||
}
|
||||
export() {
|
||||
const account = { ...this.account, actions: undefined };
|
||||
|
||||
@@ -23,8 +23,6 @@ import { EmoteBox } from './emote-box/emote-box';
|
||||
import { SliderBar } from './slider-bar/slider-bar';
|
||||
import { SpriteBox } from './sprite-box/sprite-box';
|
||||
import { SpriteSelection } from './sprite-selection/sprite-selection';
|
||||
import { SupportButton } from './support-button/support-button';
|
||||
import { SupporterPony } from './supporter-pony/supporter-pony';
|
||||
import { SetSelection, SetOutlineHidden } from './set-selection/set-selection';
|
||||
import { CheckBox } from './check-box/check-box';
|
||||
import { PortraitBox } from './portrait-box/portrait-box';
|
||||
@@ -73,6 +71,8 @@ import { dropdownDirectives } from './directives/dropdown';
|
||||
import { SaveActiveTab } from './directives/saveActiveTab';
|
||||
|
||||
import { SiteNamePipe } from './pipes/siteName';
|
||||
import { VisitPTButton } from './visit-pt-button/visit-pt-button';
|
||||
import { VisitPTPony } from './visit-pt-pony/visit-pt-pony';
|
||||
|
||||
const declarations = [
|
||||
ActionBar,
|
||||
@@ -89,8 +89,8 @@ const declarations = [
|
||||
SliderBar,
|
||||
SpriteBox,
|
||||
SpriteSelection,
|
||||
SupportButton,
|
||||
SupporterPony,
|
||||
VisitPTButton,
|
||||
VisitPTPony,
|
||||
SetSelection,
|
||||
SetOutlineHidden,
|
||||
CheckBox,
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
a.btn.btn-lg.btn-outline-patreon.btn-block.mb-2(
|
||||
*ngIf="patreonLink" (mouseenter)="pony.excite()" (mouseout)="pony.reset()" [href]="patreonLink" target="_blank"
|
||||
rel="noopener noreferrer")
|
||||
| {{supporter ? 'Thank you for supporting us!' : 'Support us on Patreon!'}}
|
||||
svg.patreon-logo(xmlns="http://www.w3.org/2000/svg" viewBox="0 0 150 150")
|
||||
circle(fill="#f9685f" cx="75" cy="75" r="75")
|
||||
path(fill="#052d49" d="M31.729 27.659h17.578v95.888H31.729z")
|
||||
circle(fill="#fff" cy="63.565" cx="95.783" r="35.955")
|
||||
.supporter-pony
|
||||
supporter-pony(#pony [scale]="2")
|
||||
@@ -1,17 +0,0 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Model } from '../../services/model';
|
||||
import { supporterLink } from '../../../client/data';
|
||||
|
||||
@Component({
|
||||
selector: 'support-button',
|
||||
templateUrl: 'support-button.pug',
|
||||
styleUrls: ['support-button.scss'],
|
||||
})
|
||||
export class SupportButton {
|
||||
readonly patreonLink = supporterLink;
|
||||
constructor(private model: Model) {
|
||||
}
|
||||
get supporter() {
|
||||
return this.model.supporter;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
a.btn.btn-lg.btn-pt.btn-outline-primary.btn-block.mb-2(
|
||||
*ngIf="enableVisitPTButton" (mouseenter)="pony.select()" (mouseout)="pony.reset()" [href]="ptLink" target="_blank"
|
||||
rel="noopener noreferrer")
|
||||
.pt-logo
|
||||
img.pixelart.logo(revSrc="images/logo-small.png")
|
||||
| {{'Visit Pony Town main server!'}}
|
||||
.visit-pt-pony
|
||||
visit-pt-pony(#pony [scale]="2")
|
||||
+14
-8
@@ -12,30 +12,36 @@
|
||||
}
|
||||
}
|
||||
|
||||
.patreon-logo {
|
||||
.btn-pt {
|
||||
padding: 1.0rem;
|
||||
font-weight: 500;
|
||||
//height: 60px;
|
||||
}
|
||||
|
||||
.pt-logo {
|
||||
position: absolute;
|
||||
left: 8px;
|
||||
top: 5px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
top: 6px;
|
||||
width: 37px;
|
||||
height: 47px;
|
||||
|
||||
@media (max-width: 320px) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.supporter-pony {
|
||||
.visit-pt-pony {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
height: 70px;
|
||||
height: 80px;
|
||||
width: 100px;
|
||||
overflow: hidden;
|
||||
border-radius: $border-radius-lg - 2px;
|
||||
|
||||
> supporter-pony {
|
||||
> visit-pt-pony {
|
||||
position: absolute;
|
||||
bottom: -95px;
|
||||
bottom: -80px;
|
||||
left: -20px;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'visit-pt-button',
|
||||
templateUrl: 'visit-pt-button.pug',
|
||||
styleUrls: ['visit-pt-button.scss'],
|
||||
})
|
||||
export class VisitPTButton {
|
||||
readonly ptLink = 'http://pony.town';
|
||||
readonly enableVisitPTButton = true;
|
||||
constructor() {
|
||||
}
|
||||
}
|
||||
+42
-15
@@ -1,41 +1,42 @@
|
||||
import { Component, OnInit, OnDestroy, Input, ViewChild } from '@angular/core';
|
||||
import { defaultExpression } from '../../../client/ponyUtils';
|
||||
import { defaultPonyState } from '../../../client/ponyHelpers';
|
||||
import { SUPPORTER_PONY } from '../../../common/constants';
|
||||
import { Expression, Muzzle, HeadAnimation, Iris } from '../../../common/interfaces';
|
||||
import { excite } from '../../../client/ponyAnimations';
|
||||
import { Expression, Muzzle, HeadAnimation, BodyAnimation, Eye } from '../../../common/interfaces';
|
||||
import { excite_meno, happy_tongue_meno, stand, boop, happy_tongue_meno_2 } from '../../../client/ponyAnimations';
|
||||
import { FrameService, FrameLoop } from '../../services/frameService';
|
||||
import { CharacterPreview } from '../character-preview/character-preview';
|
||||
import { decompressPonyString } from '../../../common/compressPony';
|
||||
|
||||
const BLEP: Expression = {
|
||||
...defaultExpression,
|
||||
left: Eye.Neutral2,
|
||||
right: Eye.Neutral2,
|
||||
muzzle: Muzzle.Blep,
|
||||
};
|
||||
|
||||
const EXCITED: Expression = {
|
||||
...defaultExpression,
|
||||
left: Eye.Neutral2,
|
||||
right: Eye.Neutral2,
|
||||
muzzle: Muzzle.SmileOpen,
|
||||
};
|
||||
|
||||
const DERP: Expression = {
|
||||
...defaultExpression,
|
||||
muzzle: Muzzle.SmileOpen,
|
||||
leftIris: Iris.Up,
|
||||
};
|
||||
const MENO = 'DBWIzP8imd08//D19fVazSjcwf1GhLNEiMxENSovLy/NsIdJQDnGqYBiSztWQTM6LychEnE/KRX///9WPeE1HbSpBUEIIASwgEIAAAAAbIAgCFMY34AHAAjwgCMRQCVLY38IDhAAwmFBz4fAIxjKM6SjGlaxjWtYgjGI';
|
||||
|
||||
@Component({
|
||||
selector: 'supporter-pony',
|
||||
templateUrl: 'supporter-pony.pug',
|
||||
selector: 'visit-pt-pony',
|
||||
templateUrl: 'visit-pt-pony.pug',
|
||||
})
|
||||
export class SupporterPony implements OnInit, OnDestroy {
|
||||
export class VisitPTPony implements OnInit, OnDestroy {
|
||||
@ViewChild('characterPreview', { static: true }) characterPreview!: CharacterPreview;
|
||||
@Input() scale = 3;
|
||||
pony = decompressPonyString(SUPPORTER_PONY);
|
||||
pony = decompressPonyString(MENO);
|
||||
state = defaultPonyState();
|
||||
private expression?: Expression;
|
||||
private headAnimation?: HeadAnimation;
|
||||
private headTime = 0;
|
||||
private bodyAnimation?: BodyAnimation;
|
||||
private bodyTime = 0;
|
||||
private loop: FrameLoop;
|
||||
constructor(frameService: FrameService) {
|
||||
this.loop = frameService.create(delta => this.tick(delta));
|
||||
@@ -46,16 +47,29 @@ export class SupporterPony implements OnInit, OnDestroy {
|
||||
ngOnDestroy() {
|
||||
this.loop.destroy();
|
||||
}
|
||||
excite() {
|
||||
select() {
|
||||
this.headTime = 0;
|
||||
this.headAnimation = excite;
|
||||
this.expression = Math.random() < 0.2 ? DERP : EXCITED;
|
||||
this.bodyTime = 0;
|
||||
this.expression = EXCITED;
|
||||
this.bodyAnimation = Math.random() < 0.25 ? boop : stand;
|
||||
|
||||
const headRandom = Math.random();
|
||||
if (headRandom < 0.5) {
|
||||
this.headAnimation = excite_meno;
|
||||
}
|
||||
else if (headRandom < 0.8) {
|
||||
this.headAnimation = happy_tongue_meno;
|
||||
}
|
||||
else {
|
||||
this.headAnimation = happy_tongue_meno_2;
|
||||
}
|
||||
}
|
||||
reset() {
|
||||
this.expression = undefined;
|
||||
}
|
||||
private tick(delta: number) {
|
||||
this.headTime += delta;
|
||||
this.bodyTime += delta;
|
||||
|
||||
if (this.headAnimation) {
|
||||
const frame = Math.floor(this.headTime * this.headAnimation.fps);
|
||||
@@ -83,6 +97,19 @@ export class SupporterPony implements OnInit, OnDestroy {
|
||||
}
|
||||
}
|
||||
|
||||
if (this.bodyAnimation) {
|
||||
const frame = Math.floor(this.bodyTime * this.bodyAnimation.fps * 0.75);
|
||||
|
||||
if (frame >= this.bodyAnimation.frames.length && !this.bodyAnimation.loop) {
|
||||
this.bodyAnimation = undefined;
|
||||
this.state.animation = stand;
|
||||
this.state.animationFrame = 0;
|
||||
} else {
|
||||
this.state.animation = this.bodyAnimation;
|
||||
this.state.animationFrame = frame % this.bodyAnimation.frames.length;
|
||||
}
|
||||
}
|
||||
|
||||
this.state.expression = this.expression;
|
||||
}
|
||||
}
|
||||
@@ -113,7 +113,6 @@ export class ToolsUI implements OnInit, OnDestroy {
|
||||
],
|
||||
};
|
||||
game.onClock.next('00:00');
|
||||
game.failedFBO = true;
|
||||
game.send = <T>(action: (server: any) => T) => action({
|
||||
action() { },
|
||||
select() { },
|
||||
|
||||
Reference in New Issue
Block a user