Files
NGECore2/src/services/EntertainmentService.java
T

961 lines
35 KiB
Java

package services;
import java.nio.ByteOrder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import java.util.Vector;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import main.NGECore;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import protocol.swg.ObjControllerMessage;
import protocol.swg.OkMessage;
import protocol.swg.PlayClientEffectObjectMessage;
import protocol.swg.objectControllerObjects.BuffBuilderChangeMessage;
import protocol.swg.objectControllerObjects.BuffBuilderEndMessage;
import protocol.swg.objectControllerObjects.BuffBuilderStartMessage;
import protocol.swg.objectControllerObjects.ImageDesignMessage;
import resources.common.BuffBuilder;
import resources.common.Console;
import resources.common.IDAttribute;
import resources.common.MathUtilities;
import resources.common.ObjControllerOpcodes;
import resources.common.Performance;
import resources.common.PerformanceEffect;
import resources.common.RGB;
import resources.common.StringUtilities;
import resources.datatables.Posture;
import resources.objects.Buff;
import resources.objects.BuffItem;
import resources.objects.SWGList;
import resources.objects.SkillMod;
import resources.objects.creature.CreatureObject;
import resources.objects.player.PlayerObject;
import resources.objects.tangible.TangibleObject;
import resources.visitors.IDManagerVisitor;
import services.sui.SUIService.InputBoxType;
import services.sui.SUIWindow;
import services.sui.SUIWindow.SUICallback;
import services.sui.SUIWindow.Trigger;
import engine.clientdata.ClientFileManager;
import engine.clientdata.visitors.DatatableVisitor;
import engine.clients.Client;
import engine.resources.objects.SWGObject;
import engine.resources.service.INetworkDispatch;
import engine.resources.service.INetworkRemoteEvent;
public class EntertainmentService implements INetworkDispatch {
private NGECore core;
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
private Vector<BuffBuilder> buffBuilderSkills = new Vector<BuffBuilder>();
//FIXME: create a wrapper class for double key lookup maps
private ConcurrentHashMap<String,Performance> performances = new ConcurrentHashMap<String,Performance>();
private ConcurrentHashMap<Integer,Performance> performancesByIndex = new ConcurrentHashMap<Integer,Performance>();
private ConcurrentHashMap<Integer,Performance> danceMap = new ConcurrentHashMap<Integer,Performance>();
private ConcurrentHashMap<String, Short> designMap = new ConcurrentHashMap<String, Short>();
private Random ranWorkshop = new Random();
private Map<String, PerformanceEffect> performanceEffects = new ConcurrentHashMap<String, PerformanceEffect>();
public EntertainmentService(NGECore core) {
this.core = core;
populateSkillCaps();
populatePerformanceTable();
populatePerformanceEffects();
registerCommands();
loadCharacterCustomizationData();
}
@Override
public void insertOpcodes(Map<Integer, INetworkRemoteEvent> swgOpcodes, Map<Integer, INetworkRemoteEvent> objControllerOpcodes) {
objControllerOpcodes.put(ObjControllerOpcodes.IMAGE_DESIGN_CHANGE, new INetworkRemoteEvent() {
@Override
public void handlePacket(IoSession session, IoBuffer data) throws Exception {
data.order(ByteOrder.LITTLE_ENDIAN);
Client client = core.getClient(session);
if(client == null)
return;
SWGObject sender = client.getParent();
if(sender == null)
return;
ImageDesignMessage sentPacket = new ImageDesignMessage();
sentPacket.deserialize(data);
CreatureObject designTarget = (CreatureObject) core.objectService.getObject(sentPacket.getTargetId());
CreatureObject designer = (CreatureObject) core.objectService.getObject(sentPacket.getDesignerId());
if (designTarget == null || designer == null)
return;
if (designTarget.getClient() == null || designTarget.getClient().getSession() == null)
return;
if (designer.getClient() == null || designer.getClient().getSession() == null)
return;
Vector<IDAttribute> colorAttributes = sentPacket.getColorAttributes();
Vector<IDAttribute> bodyAttributes = sentPacket.getBodyAttributes();
// TODO: Attribute check for colors?
if (bodyAttributes != null) {
for (IDAttribute atr : bodyAttributes) {
//System.out.println("ATTRIBUTE: " + atr.getName() + " value of " + atr.getFloatValue());
if (atr.getFloatValue() > 1f || atr.getFloatValue() < 0) { // RIP Height Exploit <3
return;
}
}
}
/*if (colorAttributes != null) {
for (IDAttribute atr : colorAttributes) {
System.out.println("COLOR ATTRIBUTE: " + atr.getName() + " value of " + atr.getValue());
}
}*/
if (sentPacket.getTargetId() != sentPacket.getDesignerId()) {
if (sentPacket.isCustomerAccepted() && sentPacket.isDesignerCommited()) {
System.out.print("Both Accepted!");
sentPacket.setEndMessage(true);
int fee = sentPacket.getMoneyDemanded() + sentPacket.getMoneyOffered();
if (fee > 0) {
int payersCash = designTarget.getCashCredits();
if (payersCash < fee) {
if (designTarget != designer) {
ObjControllerMessage msg = new ObjControllerMessage(0x0B, sentPacket);
designTarget.getClient().getSession().write(msg.serialize());
// Window is closed already, so this shouldn't be necessary
//ObjControllerMessage designMsg = new ObjControllerMessage(0x0B, sentPacket);
//designer.getClient().getSession().write(designMsg.serialize());
designTarget.sendSystemMessage("You don't have enough credits to pay the fee.", (byte) 0);
designer.sendSystemMessage("Your target did not have the required payment fee", (byte) 0);
}
}else {
// TODO: Apply customization
designTarget.setCashCredits(designTarget.getCashCredits() - fee);
designer.setCashCredits(designer.getCashCredits() + fee);
handleImageDesign(designer, designTarget, colorAttributes, bodyAttributes, sentPacket.getHair(), sentPacket.getHoloEmote());
sentPacket.setEndMessage(true);
sentPacket.setObjectId(designTarget.getObjectId());
ObjControllerMessage msg = new ObjControllerMessage(0x0B, sentPacket);
designTarget.getClient().getSession().write(msg.serialize());
}
} else {
handleImageDesign(designer, designTarget, colorAttributes, bodyAttributes, sentPacket.getHair(), sentPacket.getHoloEmote());
sentPacket.setEndMessage(true);
sentPacket.setObjectId(designTarget.getObjectId());
ObjControllerMessage msg = new ObjControllerMessage(0x0B, sentPacket);
designTarget.getClient().getSession().write(msg.serialize());
}
} else if (sentPacket.getObjectId() == designTarget.getObjectId()) {
sentPacket.setObjectId(designer.getObjectId());
ObjControllerMessage msg = new ObjControllerMessage(0x0B, sentPacket);
designer.getClient().getSession().write(msg.serialize());
} else if (sentPacket.getObjectId() == designer.getObjectId()) {
sentPacket.setObjectId(designTarget.getObjectId());
ObjControllerMessage msg = new ObjControllerMessage(0x0B, sentPacket);
designTarget.getClient().getSession().write(msg.serialize());
}
} else {
// No need to send a close packet message because the client automatically closes the ID window for the Desginer when they commit
if (sentPacket.isDesignerCommited())
handleImageDesign(designer, designTarget, colorAttributes, bodyAttributes, sentPacket.getHair(), sentPacket.getHoloEmote());
else
return;
}
}
});
objControllerOpcodes.put(ObjControllerOpcodes.IMAGE_DESIGN_END, new INetworkRemoteEvent() {
@Override
public void handlePacket(IoSession session, IoBuffer data) throws Exception {
data.order(ByteOrder.LITTLE_ENDIAN);
Client client = core.getClient(session);
if(client == null)
return;
SWGObject sender = client.getParent();
if(sender == null)
return;
ImageDesignMessage sentPacket = new ImageDesignMessage();
sentPacket.deserialize(data);
if (sentPacket.getTargetId() == sentPacket.getDesignerId())
return;
if (sentPacket.getObjectId() == sentPacket.getDesignerId()) {
CreatureObject target = (CreatureObject) core.objectService.getObject(sentPacket.getTargetId());
if (target == null)
return;
sentPacket.setEndMessage(true);
sentPacket.setObjectId(target.getObjectId());
ObjControllerMessage endMessage = new ObjControllerMessage(0x0B, sentPacket);
target.getClient().getSession().write(endMessage.serialize());
} else if (sentPacket.getObjectId() == sentPacket.getTargetId()) {
CreatureObject designer = (CreatureObject) core.objectService.getObject(sentPacket.getDesignerId());
if (designer == null)
return;
sentPacket.setEndMessage(true);
sentPacket.setObjectId(designer.getObjectId());
ObjControllerMessage endMessage = new ObjControllerMessage(0x0B, sentPacket);
designer.getClient().getSession().write(endMessage.serialize());
}
}
});
objControllerOpcodes.put(ObjControllerOpcodes.BUFF_BUILDER_END, new INetworkRemoteEvent() {
@Override
public void handlePacket(IoSession session, IoBuffer data) throws Exception {
data.order(ByteOrder.LITTLE_ENDIAN);
Client client = core.getClient(session);
if(client == null)
return;
SWGObject sender = client.getParent();
if(sender == null)
return;
BuffBuilderEndMessage sentPacket = new BuffBuilderEndMessage();
sentPacket.deserialize(data);
SWGObject buffer = core.objectService.getObject(sentPacket.getBufferId());
SWGObject buffRecipient = core.objectService.getObject(sentPacket.getBuffRecipientId());
if(buffer == null || buffRecipient == null)
return;
// No need to send end packet when buffing yourself.
if (buffRecipient != buffer) {
if(buffRecipient.getClient() == null || buffRecipient.getClient().getSession() == null)
return;
if (sender.getObjectId() == buffer.getObjectId()) {
// send close packet to recipient
BuffBuilderEndMessage end = new BuffBuilderEndMessage(sentPacket);
end.setObjectId(buffRecipient.getObjectId());
end.setBufferId(buffer.getObjectId());
end.setBuffRecipientId(buffRecipient.getObjectId());
ObjControllerMessage closeMessage = new ObjControllerMessage(0x0B, end);
buffRecipient.getClient().getSession().write(closeMessage.serialize());
}
if (sender.getObjectId() == buffRecipient.getObjectId()) {
// send close packet to buffer
BuffBuilderEndMessage end = new BuffBuilderEndMessage(sentPacket);
end.setObjectId(buffer.getObjectId());
end.setBufferId(buffer.getObjectId());
end.setBuffRecipientId(buffRecipient.getObjectId());
ObjControllerMessage closeMessage = new ObjControllerMessage(0x0B, end);
buffer.getClient().getSession().write(closeMessage.serialize());
CreatureObject cre = (CreatureObject) buffer;
cre.sendSystemMessage("The buff recipient cancelled the buff builder session.", (byte) 0);
}
}
}
});
objControllerOpcodes.put(ObjControllerOpcodes.BUFF_BUILDER_CHANGE, new INetworkRemoteEvent() {
@Override
public void handlePacket(IoSession session, IoBuffer data) throws Exception {
data.order(ByteOrder.LITTLE_ENDIAN);
Client client = core.getClient(session);
if(client == null)
return;
SWGObject sender = client.getParent();
if(sender == null)
return;
BuffBuilderChangeMessage sentPacket = new BuffBuilderChangeMessage();
sentPacket.deserialize(data);
Vector<BuffItem> statBuffs = sentPacket.getStatBuffs();
CreatureObject buffer = (CreatureObject) core.objectService.getObject(sentPacket.getBufferId());
CreatureObject buffRecipient = (CreatureObject) core.objectService.getObject(sentPacket.getBuffRecipientId());
if (buffer != buffRecipient) {
BuffBuilderChangeMessage changeMessage = new BuffBuilderChangeMessage();
changeMessage.setBuffCost(sentPacket.getBuffCost());
changeMessage.setTime(sentPacket.getTime());
changeMessage.setBufferId(buffer.getObjectId());
changeMessage.setBuffRecipientId(buffRecipient.getObjectId());
if (!statBuffs.isEmpty())
changeMessage.setStatBuffs(statBuffs);
if (sentPacket.getAccepted() == true && sentPacket.getBuffRecipientAccepted() == 1) {
if (sentPacket.getBuffCost() > 0) {
if (buffRecipient.getCashCredits() >= sentPacket.getBuffCost()) {
buffRecipient.setCashCredits(buffRecipient.getCashCredits() - sentPacket.getBuffCost());
} else {
return;
}
}
giveInspirationBuff(buffRecipient, buffer, statBuffs);
BuffBuilderEndMessage endBuilder = new BuffBuilderEndMessage(changeMessage);
endBuilder.setObjectId(buffer.getObjectId());
BuffBuilderEndMessage endRecipient = new BuffBuilderEndMessage(changeMessage);
endRecipient.setObjectId(buffRecipient.getObjectId());
ObjControllerMessage closeBuilder = new ObjControllerMessage(0x0B, endBuilder);
buffer.getClient().getSession().write(closeBuilder.serialize());
ObjControllerMessage closeRecipient = new ObjControllerMessage(0x0B, endRecipient);
buffRecipient.getClient().getSession().write(closeRecipient.serialize());
} else if (sentPacket.getAccepted() == true && sentPacket.getBuffRecipientAccepted() == 0) {
changeMessage.setAccepted(true);
changeMessage.setObjectId(buffRecipient.getObjectId());
ObjControllerMessage objMsg = new ObjControllerMessage(0x0B, changeMessage);
buffRecipient.getClient().getSession().write(objMsg.serialize());
} else {
changeMessage.setAccepted(false);
changeMessage.setObjectId(sentPacket.getBuffRecipientId());
ObjControllerMessage objMsg = new ObjControllerMessage(0x0B, changeMessage);
buffRecipient.getClient().getSession().write(objMsg.serialize());
}
} else {
if (sentPacket.getAccepted() == true) {
giveInspirationBuff(buffRecipient, buffer, statBuffs);
BuffBuilderEndMessage endBuilder = new BuffBuilderEndMessage(sentPacket);
endBuilder.setObjectId(buffer.getObjectId());
ObjControllerMessage objMsg = new ObjControllerMessage(0x0B, endBuilder);
buffRecipient.getClient().getSession().write(objMsg.serialize());
}
}
}
});
}
private void populatePerformanceTable() {
try {
DatatableVisitor PerformanceVisitor = ClientFileManager.loadFile("datatables/performance/performance.iff", DatatableVisitor.class);
//rformanceVisitor.
for (int r = 0; r < PerformanceVisitor.getRowCount(); r++) {
Performance p = new Performance();
/* for (int j=0; j < PerformanceVisitor.getColumnCount(); j++) {
System.out.println(j + ": " + PerformanceVisitor.getObject(r, j));
}*/
p.setPerformanceName( ( (String) PerformanceVisitor.getObject(r, 0) ).toLowerCase());
p.setInstrumentAudioId((int) PerformanceVisitor.getObject(r, 1));
p.setRequiredSong((String) PerformanceVisitor.getObject(r, 2));
p.setRequiredInstrument((String) PerformanceVisitor.getObject(r, 3));
p.setRequiredDance((String) PerformanceVisitor.getObject(r, 4));
p.setDanceVisualId((int) PerformanceVisitor.getObject(r, 5));
p.setActionPointsPerLoop((int) PerformanceVisitor.getObject(r, 6));
p.setLoopDuration((float) PerformanceVisitor.getObject(r, 7));
p.setType((int) PerformanceVisitor.getObject(r, 8));
p.setBaseXp((int) PerformanceVisitor.getObject(r, 9));
p.setFlourishXpMod((int) PerformanceVisitor.getObject(r, 10));
p.setHealMindWound((int) PerformanceVisitor.getObject(r, 11));
p.setHealShockWound((int) PerformanceVisitor.getObject(r, 12));
p.setRequiredSkillMod((String) PerformanceVisitor.getObject(r, 13));
p.setRequiredSkillModValue((int) PerformanceVisitor.getObject(r, 14));
p.setMainloop((String) PerformanceVisitor.getObject(r, 15));
p.setFlourish1((String) PerformanceVisitor.getObject(r, 16));
p.setFlourish2((String) PerformanceVisitor.getObject(r, 17));
p.setFlourish3((String) PerformanceVisitor.getObject(r, 18));
p.setFlourish4((String) PerformanceVisitor.getObject(r, 19));
p.setFlourish5((String) PerformanceVisitor.getObject(r, 20));
p.setFlourish6((String) PerformanceVisitor.getObject(r, 21));
p.setFlourish7((String) PerformanceVisitor.getObject(r, 22));
p.setFlourish8((String) PerformanceVisitor.getObject(r, 23));
p.setIntro((String) PerformanceVisitor.getObject(r, 24));
p.setOutro((String) PerformanceVisitor.getObject(r, 25));
p.setLineNumber(r);
if (p.getType() == -1788534963) {
danceMap.put(new Integer(p.getDanceVisualId()), p);
}
performances.put(p.getPerformanceName(), p);
performancesByIndex.put(r, p);
}
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
}
private void populateSkillCaps() {
try {
DatatableVisitor buffBuilder = ClientFileManager.loadFile("datatables/buff/buff_builder.iff", DatatableVisitor.class);
for (int r = 0; r < buffBuilder.getRowCount(); r++) {
String skillName = ((String) buffBuilder.getObject(r, 0));
String category = ((String) buffBuilder.getObject(r, 1));
String statAffects = ((String) buffBuilder.getObject(r, 2));
int maxTimes = ((int) buffBuilder.getObject(r, 3));
int cost = ((int) buffBuilder.getObject(r, 4));
int affectAmount = ((int) buffBuilder.getObject(r, 5));
String requiredExpertise = ((String) buffBuilder.getObject(r, 6));
BuffBuilder item = new BuffBuilder();
item.setStatName(skillName);
item.setCategory(category);
item.setStatAffects(statAffects);
item.setMaxTimesApplied(maxTimes);
item.setCost(cost);
item.setAffectAmount(affectAmount);
item.setRequiredExpertise(requiredExpertise);
buffBuilderSkills.add(item);
}
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
}
private void populatePerformanceEffects() {
try {
DatatableVisitor effects = ClientFileManager.loadFile("datatables/performance/perform_effect.iff", DatatableVisitor.class);
for (int r = 0; r < effects.getRowCount(); r++) {
String effectName = ((String) effects.getObject(r, 0));
String performanceType = ((String) effects.getObject(r, 1));
int requiredSkillModValue = ((int) effects.getObject(r, 2));
Boolean requiredPerforming = ((Boolean) effects.getObject(r, 3));
int targetType = ((int) effects.getObject(r, 4));
float effectDuration = ((float) effects.getObject(r, 5));
int effectActionCost = ((int) effects.getObject(r, 6));
PerformanceEffect item = new PerformanceEffect();
item.setEffectActionCost(effectActionCost);
item.setEffectDuration(effectDuration);
item.setName(effectName);
item.setPerformanceType(performanceType);
item.setRequiredPerforming(requiredPerforming);
item.setRequiredSkillModValue(requiredSkillModValue);
item.setTargetType(targetType);
performanceEffects.put(effectName.toLowerCase(), item);
}
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
}
private void registerCommands() {
core.commandService.registerCommand("bandflourish");
core.commandService.registerCommand("flourish");
core.commandService.registerAlias("flo","flourish");
core.commandService.registerCommand("groupdance");
core.commandService.registerCommand("startdance");
core.commandService.registerCommand("stopdance");
core.commandService.registerCommand("watch");
//core.commandService.registerCommand("stopwatching"); // SWGList error
core.commandService.registerCommand("holoEmote");
core.commandService.registerCommand("covercharge");
//core.commandService.registerCommand("en_holographic_recall");
//core.commandService.registerCommand("en_holographic_image");
core.commandService.registerCommand("imagedesign");
// TODO: Add /bandsolo, /bandpause, /changeBandMusic, /changeDance, /changeGroupDance, /changeMusic
// Entertainer Effects
core.commandService.registerCommand("centerStage");
core.commandService.registerCommand("colorSwirl");
core.commandService.registerCommand("colorlights");
core.commandService.registerCommand("floorLights"); // referred to also as Dance Floor
core.commandService.registerCommand("dazzle");
core.commandService.registerCommand("distract");
core.commandService.registerCommand("featuredSolo");
core.commandService.registerCommand("firejet");
core.commandService.registerCommand("firejet2");
core.commandService.registerCommand("laserShow");
core.commandService.registerCommand("smokebomb");
core.commandService.registerCommand("spotlight");
core.commandService.registerCommand("ventriloquism");
}
public void giveInspirationBuff(CreatureObject reciever, CreatureObject buffer, Vector<BuffItem> buffVector) {
Vector<BuffBuilder> availableStats = buffBuilderSkills;
Vector<BuffItem> stats = new Vector<BuffItem>();
for (BuffItem item : buffVector) {
for(BuffBuilder builder : availableStats) {
if(builder.getStatName().equalsIgnoreCase(item.getSkillName())) {
if(builder.getMaxTimesApplied() < item.getInvested())
return;
// Ent. Expertise Percent + (invested points * affect amount) = stat
int bonusPoints = (int) (builder.getAffectAmount() *((float) item.getEntertainerBonus()/100f));
int affectTotal = bonusPoints + (item.getInvested() * builder.getAffectAmount());
BuffItem stat = new BuffItem(builder.getStatAffects(), item.getInvested(), item.getEntertainerBonus());
stat.setAffectAmount(affectTotal);
stats.add(stat);
}
}
}
reciever.setAttachment("buffWorkshop", stats);
if (buffer == reciever)
reciever.setAttachment("inspireDuration", 215);
//PlayerObject rPlayer = (PlayerObject) reciever.getSlottedObject("ghost");
//long timeStamp = 0;
//if (reciever.getAttachment("buffWorkshopTimestamp") != null)
//timeStamp = (long) reciever.getAttachment("buffWorkshopTimestamp");
core.buffService.addBuffToCreature(reciever, "buildabuff_inspiration", buffer);
/*if (core.buffService.addBuffToCreature(reciever, "buildabuff_inspiration", buffer) && !rPlayer.getProfession().equals("entertainer_1a")) {
if (timeStamp == 0 || (System.currentTimeMillis() - timeStamp > 86400000)) {
float random = ranWorkshop.nextFloat();
if (random < 0.75f) {
if(rPlayer.getProfession().contains("trader")) { core.collectionService.addCollection(buffer, "prof_trader"); }
else {
core.collectionService.addCollection(buffer, rPlayer.getProfession());
}
}
} else { buffer.sendSystemMessage("@collection:buffed_too_soon", (byte) 0); }
reciever.setAttachment("buffWorkshopTimestamp", System.currentTimeMillis());
}*/
}
public int getDanceVisualId(String danceName) {
Performance p = performances.get(danceName);
//if 0 , then it's no dance. need to handle that in the script.
return ((p == null) ? 0 : p.getDanceVisualId());
}
public Map<Long,String> getAvailableDances(CreatureObject actor) {
Map<Long,String> dances = new HashMap<Long, String>();
for (int index : danceMap.keySet()) {
if (!canDance(actor, danceMap.get(index) )) { continue; }
dances.put( new Long( danceMap.get(index).getDanceVisualId() ), danceMap.get(index).getPerformanceName() );
}
return dances;
}
public boolean isDance(int visualId) {
return ( danceMap.get(visualId) != null ) ;
}
public boolean canDance(CreatureObject actor, Performance dance) {
if (actor.hasAbility(dance.getRequiredDance())) {
return true;
}
return false;
}
public boolean canDance(CreatureObject actor, int visualId) {
if (!isDance(visualId)) { return false; }
return canDance(actor, danceMap.get(visualId));
}
public Performance getDance(int visualId) {
return danceMap.get(visualId);
}
public Performance getPerformance(String name) {
return performances.get(name);
}
public Performance getPerformanceByIndex(int index) {
return performancesByIndex.get(index);
}
public Map<String, PerformanceEffect> getPerformanceEffects() {
return performanceEffects;
}
public void startPerformance(CreatureObject actor, int performanceId, int performanceCounter, String skillName, boolean isDance) {
actor.setPerformanceId(performanceId, isDance);
actor.setPerformanceCounter(performanceCounter);
actor.setCurrentAnimation(skillName);
actor.setPerformanceType(isDance);
actor.startPerformance();
}
public void startPerformanceExperience(final CreatureObject entertainer) {
final ScheduledFuture<?> experienceTask = scheduler.scheduleAtFixedRate(() -> {
Performance p = performancesByIndex.get(entertainer.getPerformanceId());
if (p == null) {
entertainer.setFlourishCount(0);
return;
}
int floXP = p.getFlourishXpMod();
int floCount = entertainer.getFlourishCount();
//FIXME: this is not an accurate implementation yet. It needs group bonuses and other things.
int XP = (int) Math.round( ((floCount > 2) ? 2 : floCount) * floXP * 3.8 );
entertainer.setFlourishCount(0);
core.playerService.giveExperience(entertainer, XP);
}, 10000, 10000, TimeUnit.MILLISECONDS);
entertainer.setEntertainerExperience(experienceTask);
}
public void startSpectating(final CreatureObject spectator, final CreatureObject performer, boolean spectateType) {
// visual
if (spectator.getPerformanceWatchee() == performer && spectateType)
spectator.getPerformanceWatchee().removeAudience(spectator);
// music
else if (spectator.getPerformanceListenee() == performer && !spectateType)
spectator.getPerformanceListenee().removeAudience(spectator);
spectator.setPerformanceWatchee(performer);
performer.addAudience(spectator);
spectator.setMoodAnimation("entertained");
final ScheduledFuture<?> spectatorTask = scheduler.scheduleAtFixedRate(() -> {
if (spectator.getPosition().getDistance2D(performer.getWorldPosition()) > (float) 70) {
if(((performer.getPerformanceType()) ? "dance" : "music").equals("dance")) {
spectator.setPerformanceWatchee(null);
spectator.sendSystemMessage("You stop watching " + performer.getCustomName() + " because " + performer.getCustomName()
+ " is out of range.", (byte) 0);
}
else {
spectator.setPerformanceListenee(null);
spectator.sendSystemMessage("You stop listening to " + performer.getCustomName() + " because " + performer.getCustomName()
+ " is out of range.", (byte) 0);
}
spectator.setMoodAnimation("neutral");
performer.removeAudience(spectator);
if (spectator.getInspirationTick().cancel(true))
spectator.getSpectatorTask().cancel(true);
}
}, 2, 2, TimeUnit.SECONDS);
spectator.setSpectatorTask(spectatorTask);
if(((PlayerObject)performer.getSlottedObject("ghost")).getProfession().equals("entertainer_1a")) {
handleInspirationTicks(spectator, performer);
}
if(spectateType)
spectator.sendSystemMessage("You start watching " + performer.getCustomName() + ".", (byte) 0);
else
spectator.sendSystemMessage("You start listening to " + performer.getCustomName() + ".", (byte) 0);
}
public void performFlourish(final CreatureObject performer, int flourish) {
if (performer.getFlourishCount() > 0 || performer.isPerformingFlourish()) {
performer.sendSystemMessage("@performance:flourish_wait_self", (byte) 0);
return;
}
Performance performance = getPerformanceByIndex(performer.getPerformanceId());
if(performance == null)
return;
String anmFlo = "skill_action_" + flourish;
if (flourish == 9)
anmFlo = "mistake";
performer.setFlourishCount(1);
performer.setPerformingFlourish(true);
performer.sendSystemMessage("@performance:flourish_perform", (byte) 0);
performer.doSkillAnimation(anmFlo);
scheduler.schedule(() -> {
performer.setFlourishCount(0);
performer.setPerformingFlourish(true);
}, (long) performance.getLoopDuration(), TimeUnit.SECONDS);
}
public boolean performEffect(final CreatureObject performer, String command, String effect, TangibleObject target) {
PerformanceEffect pEffect = performanceEffects.get(command.toLowerCase());
if(pEffect == null)
return false;
String performance = (performer.getPerformanceType()) ? "dance" : "music";
if(performer.isPerformingEffect()) {
performer.sendSystemMessage("@performance:effect_wait_self", (byte) 0);
return false;
}
if (performer.getPosture() != Posture.SkillAnimating) {
performer.sendSystemMessage("@performance:effect_not_performing", (byte) 0);
return false;
}
if(performance.equals("dance") && !pEffect.isDance() || performance.equals("music") && !pEffect.isMusic()) {
performer.sendSystemMessage("@performance:effect_not_performing_correct", (byte) 0);
return false;
}
if(performer.getAction() < pEffect.getEffectActionCost()) {
performer.sendSystemMessage("@performance:effect_too_tired", (byte) 0);
return false;
}
performer.setAction(performer.getAction() - pEffect.getEffectActionCost());
performer.setPerformingEffect(true);
if(target != null)
target.playEffectObject(effect, "");
else
performer.playEffectObject(effect, "");
scheduler.schedule(() -> {
performer.setPerformingEffect(false);
}, (long) pEffect.getEffectDuration(), TimeUnit.SECONDS);
return true;
}
public void handleInspirationTicks(final CreatureObject spectator, final CreatureObject performer) {
// http://youtu.be/WqyAde-oC7o?t=11m14s << Player watching entertainer (Has ring only, no pet, + 15 min ticks)
// TODO: Camp/Cantina checks for expertise and duration bonus %. Right now only using basic values.
final ScheduledFuture<?> inspirationTick = scheduler.scheduleAtFixedRate(() -> {
int time = 0; // current buff duration time (minutes)
int buffCap = 215; // 5 hours 35 minutes - 2 hours (buff duration increase bonus) << Taken from video, doesn't account for performance bonuses etc.
if (spectator.getAttachment("inspireDuration") != null)
time+= (int) spectator.getAttachment("inspireDuration");
if (performer.getSkillMod("expertise_en_inspire_buff_duration_increase") != null) {
SkillMod durationMod = performer.getSkillMod("expertise_en_inspire_buff_duration_increase");
buffCap += durationMod.getBase() + durationMod.getModifier();
}
if (time >= buffCap) {
spectator.setAttachment("inspireDuration", buffCap); // incase someone went over cap
spectator.getInspirationTick().cancel(true);
} else {
int entTick = 10;
if (performer.getSkillMod("expertise_en_inspire_pulse_duration_increase") != null) {
SkillMod pulseMod = performer.getSkillMod("expertise_en_inspire_pulse_duration_increase");
entTick += pulseMod.getBase() + pulseMod.getModifier();
}
int duration = (time + entTick); // minutes
int hMinutes = MathUtilities.secondsToHourMinutes(duration * 60);
int hours = MathUtilities.secondsToWholeHours(duration * 60);
spectator.showFlyText("spam", "buff_duration_tick_observer", String.valueOf(hours) + " hours , " + hMinutes + " minutes ", 0, (float) 0.66, new RGB(255, 182, 193), 3, 78);
spectator.setAttachment("inspireDuration", duration);
//System.out.println("Inspire Duration: " + spectator.getAttachment("inspireDuration") + " on " + spectator.getCustomName());
}
}, 10, 10, TimeUnit.SECONDS);
spectator.setInspirationTick(inspirationTick);
}
public void handleCoverCharge(final CreatureObject actor, final CreatureObject performer) {
final int charge = performer.getCoverCharge();
if (charge == 0)
return;
else {
SUIWindow notification = core.suiService.createMessageBox(InputBoxType.INPUT_BOX_OK, "Cover Charge", performer.getCustomName() +
" has a cover charge of " + performer.getCoverCharge() + ". Do you wish to pay it?", actor, performer, (float) 30);
Vector<String> returnParams = new Vector<String>();
returnParams.add("btnOk:Text");
notification.addHandler(0, "", Trigger.TRIGGER_OK, returnParams, (owner, eventType, returnList) -> {
if (eventType == 0) {
if (charge > actor.getCashCredits()) {
actor.sendSystemMessage("You do not have enough credits to cover the charge.", (byte) 0); // TODO: Find the message in the STF files.
return;
} else{
actor.setCashCredits(actor.getCashCredits() - charge);
actor.sendSystemMessage("You payed the cover charge of " + charge + " to " + performer.getCustomName(), (byte) 0); // TODO: Find the message in the STF files.
performer.setCashCredits(performer.getCashCredits() + charge);
startSpectating(actor, performer, performer.getPerformanceType());
}
}
});
core.suiService.openSUIWindow(notification);
}
}
private void handleImageDesign(CreatureObject designer, CreatureObject designTarget, Vector<IDAttribute> colorAttributes, Vector<IDAttribute> bodyAttributes, String hairTemplate, String holoEmote) {
if (hairTemplate != null && !hairTemplate.equals("")) {
if(!hairTemplate.startsWith("object/tangible/hair/"))
return;
String sharedHairTemplate = hairTemplate.replace("/hair_", "/shared_hair_");
TangibleObject hairObject = (TangibleObject) core.objectService.createObject(sharedHairTemplate, designTarget.getPlanet());
if (hairObject == null)
return;
TangibleObject oldHair = (TangibleObject) designTarget.getSlottedObject("hair");
if (oldHair == null)
return;
core.objectService.destroyObject(oldHair);
designTarget.add(hairObject);
designTarget.addObjectToEquipList(hairObject);
}
if (bodyAttributes != null) {
for (IDAttribute atr : bodyAttributes) {
if (atr.getName().equals("height"))
designTarget.setHeight(atr.getFloatValue());
// TODO: Body Attributes
}
}
if (colorAttributes != null) {
for (IDAttribute atr : colorAttributes) {
if (atr.getName().equals("color_hair")){
// TODO: Color Attributes
}
}
}
if (holoEmote != null) {
PlayerObject player = (PlayerObject) designTarget.getSlottedObject("ghost");
if (player != null) {
player.setHoloEmote(holoEmote);
player.setHoloEmoteUses(20);
designTarget.sendSystemMessage("@image_designer:new_holoemote", (byte) 0);
}
}
}
private void loadCharacterCustomizationData() {
try {
IDManagerVisitor visitor = ClientFileManager.loadFile("customization/customization_id_manager.iff", IDManagerVisitor.class);
designMap = visitor.getCustomizationMap();
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
}
public String getCustomizationString(int number){
synchronized (designMap) {
for (Entry<String, Short> entry : designMap.entrySet()) {
if (entry.getValue().intValue() == number) {
return entry.getKey();
}
}
}
return "";
}
public int getCustomizationValue(String customizationString) {
synchronized(designMap){
for(Entry<String, Short> entry : designMap.entrySet()) {
if (entry.getKey().equals(customizationString)) {
return entry.getValue().intValue();
}
}
}
return 0;
}
@Override
public void shutdown() {
}
}