/** * Called by the client to report its idleness state changing. We do not accumulate play time for * idle players. */ public void setIdle( ClientObject caller, boolean nowIdle, InvocationService.ConfirmListener listener) throws InvocationException { verifyIsPlayer(caller); Player player = (caller != null) ? _players.get(caller.getOid()) : null; if (player == null) { throw new InvocationException(InvocationCodes.E_ACCESS_DENIED); } if (nowIdle) { player.pauseAccrual(); } else { player.resumeAccrual(); } // let the client know all went well listener.requestProcessed(); }
/** * Notes that the supplied player completed the specified task. Computes a coin payout for the * player, transiently reports it to them and accumulates it to their stat record for actual * payout when they leave the game. */ public void completeTask( PlayerObject plobj, String questId, float payoutLevel, InvocationService.ConfirmListener listener) throws InvocationException { // sanity check if (payoutLevel < 0 || payoutLevel > 1) { log.warning( "Invalid payout", "game", where(), "caller", plobj.who(), "quest", questId, "payout", payoutLevel); throw new InvocationException(InvocationCodes.INTERNAL_ERROR); } Player player = _players.get(plobj.getOid()); if (player == null) { // cannot award players who are not currently in the game throw new InvocationException(InvocationCodes.E_ACCESS_DENIED); } // payout factor depends on accumulated play time -- if we've yet to accumulate enough data // for a calculation, guesstimate 5 mins (TODO: this should come from the default settings // in GameMetricsRecord) int flowPerHour = _runtime.money.hourlyAVRGameFlowRate; int payoutFactor = (_content.metrics.payoutFactor == 0) ? ((5 * flowPerHour) / 60) : _content.metrics.payoutFactor; // compute our quest payout; as a sanity check, cap it at one hour of payout int rawPayout = Math.round(payoutFactor * payoutLevel); int payout = Math.min(flowPerHour, rawPayout); if (payout != rawPayout) { log.warning( "Capped AVRG payout at one hour", "game", _gameId, "factor", payoutFactor, "level", payoutLevel, "wanted", rawPayout, "got", payout); } // possibly give the party bonus int partySize = _partyReg.lookupPartyPopulation(plobj); if (partySize > 0) { float partyBonus = (float) Math.pow( _runtime.money.partyGameBonusFactor, Math.min(partySize, _runtime.money.partyMaxBonusPopulation) - 1); payout = Math.round(payout * partyBonus); } // we don't actually award coins if we're the development version of the game final boolean actuallyAward = !_content.isDevelopmentVersion(); // note that they completed this task if (actuallyAward) { player.taskCompleted(payout); // accumulate the flow for this quest (to be persisted later) if (payout > 0) { _gameReg.reportCoinAward(plobj.getMemberId(), payout); } } // report task completion to the game plobj.postMessage(AVRGameObject.TASK_COMPLETED_MESSAGE, questId, payout, actuallyAward); // tell the requester that we're groovy listener.requestProcessed(); // finally, if we have pending coin awards that exceed our current coin budget, flush 'em // and trigger a recaculation of our payout rate if (actuallyAward) { int pendingCoins = 0; for (Player p : _players.values()) { pendingCoins += p.coinsAccrued; } if (pendingCoins >= _content.metrics.flowToNextRecalc) { flushAllPlayers(); } } }