mirror of
https://github.com/duckietm/Nitro-V3.git
synced 2026-06-19 23:16:21 +00:00
Merge latest duckie main with login UI
This commit is contained in:
@@ -87,6 +87,9 @@ export class AvatarEditorThumbnailsHelper
|
||||
AvatarFigurePartType.PET,
|
||||
'ptl',
|
||||
'ptr',
|
||||
AvatarFigurePartType.MISC,
|
||||
'mcl',
|
||||
'mcr',
|
||||
];
|
||||
|
||||
private static getThumbnailKey(setType: string, part: IAvatarEditorCategoryPartItem, partColors?: IPartColor[], isDisabled?: boolean): string
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
import { AvatarFigureContainer, GetAvatarRenderManager, IFigurePartSet } from '@nitrots/nitro-renderer';
|
||||
|
||||
const getFirstSelectableColorForSetType = (setType: string): number =>
|
||||
{
|
||||
const structure = GetAvatarRenderManager()?.structureData;
|
||||
|
||||
if(!structure) return -1;
|
||||
|
||||
const set = structure.getSetType(setType);
|
||||
|
||||
if(!set) return -1;
|
||||
|
||||
const palette = structure.getPalette(set.paletteID);
|
||||
|
||||
if(!palette) return -1;
|
||||
|
||||
for(const color of palette.colors.getValues())
|
||||
{
|
||||
if(!color || !color.isSelectable) continue;
|
||||
|
||||
return color.id;
|
||||
}
|
||||
|
||||
return -1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Builds a new figure string starting from the base figure and applying the
|
||||
* provided figure part set IDs (e.g. a purchasable clothing set or pet set).
|
||||
*
|
||||
* When the base figure does not already define colours for the set type being
|
||||
* applied (common for pet "pt" sets on an avatar that has never worn one), the
|
||||
* first selectable palette colour is used so the part still renders instead of
|
||||
* being dropped.
|
||||
*/
|
||||
export const BuildPurchasableClothingFigure = (baseFigure: string, setIds: number[]): string =>
|
||||
{
|
||||
const manager = GetAvatarRenderManager();
|
||||
|
||||
if(!manager) return baseFigure;
|
||||
|
||||
const container = new AvatarFigureContainer(baseFigure ?? '');
|
||||
const structure = manager.structureData;
|
||||
|
||||
for(const setId of setIds)
|
||||
{
|
||||
const partSet: IFigurePartSet = structure?.getFigurePartSet(setId);
|
||||
|
||||
if(!partSet) continue;
|
||||
|
||||
let colorIds = container.getPartColorIds(partSet.type) ?? [];
|
||||
|
||||
if(!colorIds.length)
|
||||
{
|
||||
const defaultColor = getFirstSelectableColorForSetType(partSet.type);
|
||||
|
||||
if(defaultColor >= 0) colorIds = [ defaultColor ];
|
||||
}
|
||||
|
||||
container.updatePart(partSet.type, partSet.id, colorIds);
|
||||
}
|
||||
|
||||
return container.getFigureString();
|
||||
};
|
||||
@@ -2,5 +2,6 @@ export * from './AvatarEditorAction';
|
||||
export * from './AvatarEditorColorSorter';
|
||||
export * from './AvatarEditorPartSorter';
|
||||
export * from './AvatarEditorThumbnailsHelper';
|
||||
export * from './BuildPurchasableClothingFigure';
|
||||
export * from './IAvatarEditorCategory';
|
||||
export * from './IAvatarEditorCategoryPartItem';
|
||||
|
||||
@@ -117,4 +117,14 @@ export class FurnitureOffer implements IPurchasableOffer
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public get itemIds(): string
|
||||
{
|
||||
return String(this._furniData?.id ?? '');
|
||||
}
|
||||
|
||||
public get haveOffer(): boolean
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,4 +22,6 @@ export interface IPurchasableOffer
|
||||
localizationDescription: string;
|
||||
isLazy: boolean;
|
||||
products: IProduct[];
|
||||
itemIds: string;
|
||||
haveOffer: boolean;
|
||||
}
|
||||
|
||||
@@ -30,8 +30,10 @@ export class Offer implements IPurchasableOffer
|
||||
private _products: IProduct[];
|
||||
private _badgeCode: string;
|
||||
private _bundlePurchaseAllowed: boolean = false;
|
||||
private _itemIds: string = '';
|
||||
private _haveOffer: boolean = false;
|
||||
|
||||
constructor(offerId: number, localizationId: string, isRentOffer: boolean, priceInCredits: number, priceInActivityPoints: number, activityPointType: number, giftable: boolean, clubLevel: number, products: IProduct[], bundlePurchaseAllowed: boolean)
|
||||
constructor(offerId: number, localizationId: string, isRentOffer: boolean, priceInCredits: number, priceInActivityPoints: number, activityPointType: number, giftable: boolean, clubLevel: number, products: IProduct[], bundlePurchaseAllowed: boolean, itemIds: string = '', haveOffer: boolean = false)
|
||||
{
|
||||
this._offerId = offerId;
|
||||
this._localizationId = localizationId;
|
||||
@@ -43,6 +45,8 @@ export class Offer implements IPurchasableOffer
|
||||
this._clubLevel = clubLevel;
|
||||
this._products = products;
|
||||
this._bundlePurchaseAllowed = bundlePurchaseAllowed;
|
||||
this._itemIds = itemIds || '';
|
||||
this._haveOffer = haveOffer;
|
||||
|
||||
this.setPricingModelForProducts();
|
||||
this.setPricingType();
|
||||
@@ -182,6 +186,16 @@ export class Offer implements IPurchasableOffer
|
||||
return this._products;
|
||||
}
|
||||
|
||||
public get itemIds(): string
|
||||
{
|
||||
return this._itemIds;
|
||||
}
|
||||
|
||||
public get haveOffer(): boolean
|
||||
{
|
||||
return this._haveOffer;
|
||||
}
|
||||
|
||||
private setPricingModelForProducts(): void
|
||||
{
|
||||
const products = Product.stripAddonProducts(this._products);
|
||||
@@ -244,7 +258,7 @@ export class Offer implements IPurchasableOffer
|
||||
products.push(new Product(product.productType, product.productClassId, product.extraParam, product.productCount, productData, furnitureData));
|
||||
}
|
||||
|
||||
const offer = new Offer(this.offerId, this.localizationId, this.isRentOffer, this.priceInCredits, this.priceInActivityPoints, this.activityPointType, this.giftable, this.clubLevel, products, this.bundlePurchaseAllowed);
|
||||
const offer = new Offer(this.offerId, this.localizationId, this.isRentOffer, this.priceInCredits, this.priceInActivityPoints, this.activityPointType, this.giftable, this.clubLevel, products, this.bundlePurchaseAllowed, this.itemIds, this.haveOffer);
|
||||
|
||||
offer.page = this.page;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user