Example #1
0
  /*
   * format:
   * $owner-uid;nr-spells;spell1-name;spell1-uid;spell2-name;spell2-uid;...;\n
   */
	void instance::draw_spells(puppet_ptr inPuppet, int inNrOfSpells) {

    if (!inPuppet)
      inPuppet = active_puppet_;

    const int mMaxSpellsInHand = 6;

    drawn_spells_.str("");
    drawn_spells_ << "[draw];" << inNrOfSpells << "\n";
    drawn_spells_ << "$" << inPuppet->getUID() << ";";

		// create nrSpellsPerTurn spells from the hero's deck
		Deck* lDeck = inPuppet->getDeck();

		int i;
		for (i=0; i< inNrOfSpells; ++i) {
			Spell* lSpell = lDeck->drawSpell();
			// assign UID and attach to puppet
			lSpell->setUID(generate_uid());
			inPuppet->attachSpell(lSpell);

      pass_to_lua("Spells.onDrawSpell", 2, "Pixy::Puppet", inPuppet.get(), "Pixy::Spell", lSpell);

      drawn_spells_ << lSpell->getName() << ";" << lSpell->getUID() << ";";

      lSpell = 0;
		}

    drawn_spells_ << "\n";

    // tell it to drop some spells if its hand is overflown
    drawn_spells_ << "[drop];";
    int nrOverflow = inPuppet->nrSpellsInHand() - mMaxSpellsInHand;
    //~ std::cout << "Puppet has " << inPuppet->nrSpellsInHand() << " spells in hand, an overflow of= " << nrOverflow << "\n";
    if (nrOverflow > 0) {
      drawn_spells_ << nrOverflow << "\n$" << inPuppet->getUID() << ";";
    } else
      drawn_spells_ << 0;

    Entity::spells_t const& lHand = inPuppet->getHand();
    while (inPuppet->nrSpellsInHand() > mMaxSpellsInHand) {
      Spell* lSpell = lHand.front();
      drawn_spells_ << lSpell->getUID() << ";";

      pass_to_lua("Spells.onDropSpell", 2, "Pixy::Puppet", inPuppet.get(), "Pixy::Spell", lSpell);

      inPuppet->detachSpell(lSpell->getUID());

      lSpell = 0;
    }
    drawn_spells_ << "\n";

    //~ log_->infoStream() << "sending drawn spells to Puppet " << inPuppet->getName();
    std::cout << "drawn spells:\n" << drawn_spells_.str() << "\n";

    // broadcast the data
    Event evt(EventUID::DrawSpells, EventFeedback::Ok, Event::NoFormat);
    evt.setProperty("Data", drawn_spells_.str());
    broadcast(evt);
	}
Example #2
0
	void instance::on_cast_spell(const Event& inEvt) {
    if (!inEvt.hasProperty("Spell")) {
      Event evt(inEvt);
      reject(evt);
      return;
    }

		// find the spell object
    Spell* lSpell;
		try {
      lSpell = get_spell(convertTo<int>(inEvt.getProperty("Spell")));
    } catch (invalid_uid& e) {
      // reject the event
      log_->errorStream() << "couldn't find requested Spell with id " << inEvt.getProperty("Spell");
      Event evt(inEvt);
		  reject(evt);
      return;
    }

		Entity* lCaster = lSpell->getCaster();

    assert(lCaster && lSpell);
    log_->debugStream() << "spell cast: " << lSpell->getUID() << "#" << lSpell->getName();
    log_->debugStream() << "caster: " << lCaster->getUID() << "#" << lCaster->getName();

    // allow only ALL or CASTING spells to be cast by active puppets
    if (lSpell->getPhase() != BLOCKING && active_puppet_->getUID() != lCaster->getOwner()->getUID())
    {
      Event evt(inEvt);
		  return reject(evt);
    }
    // blocking spells can only be cast when the active is not the caster
    else if (lSpell->getPhase() == BLOCKING && active_puppet_->getUID() == lCaster->getOwner()->getUID())
    {
      Event evt(inEvt);
		  return reject(evt);
    }

    Entity* lTarget = 0;
    if (inEvt.hasProperty("T")) {
      try {
        // is the target a puppet?
        lTarget = get_puppet(convertTo<int>(inEvt.getProperty("T"))).get();
        log_->debugStream() << "target: " << lTarget->getUID() << "#" << lTarget->getName();
      } catch (invalid_uid& e) {
        try {
          // a unit?
          lTarget = get_unit(convertTo<int>(inEvt.getProperty("T")));
          log_->debugStream() << "target: " << lTarget->getUID() << "#" << lTarget->getName();
        } catch (invalid_uid& e) {
          // invalid UID
          log_->errorStream() << "couldn't find spell target with id " << inEvt.getProperty("T");
          Event evt(inEvt);
          reject(evt);
          return;
        }
      }

      assert(lTarget);
      lSpell->setTarget(lTarget);
    } else {
      // if the spell requires a target, it must be given
#ifdef PARANOID
      assert(!lSpell->requiresTarget());
#else
      // gracefully reject the event
      if (lSpell->requiresTarget())
      {
        log_->errorStream()
          << "an invalid spell request#" << lSpell->getUID()
          << "; target is required but not given";
        Event e(inEvt);
        return reject(e);
      }
#endif
      // otherwise, the spell's target is the caster itself
      lSpell->setTarget(lCaster);
    }

    // verify the caster having enough resources to cast the spell
    {
      bool valid = true;
      if (lCaster->getRank() == PUPPET)
      {
        if (lSpell->getCostWP() > ((Puppet*)lCaster)->getWP())
          valid = valid && false;

        // heroes can't have less than 1 channel
        if (lSpell->getCostChannels() >= ((Puppet*)lCaster)->getChannels())
          valid = valid && false;
      }

      if (lSpell->getCostHP() > lCaster->getHP())
        valid = valid && false;


      if (!valid)
      {
        if (lCaster->getRank() == PUPPET)
        {
          Puppet* tCaster = (Puppet*)lCaster;
          log_->errorStream()
            << "caster" << tCaster->getUID()
            << " failed the resources requirements of the spell" << lSpell->getUID()
            << " : \t "
            << lSpell->getCostWP() << ":" << lSpell->getCostHP() << ":" << lSpell->getCostChannels()
            << " vs "
            << tCaster->getWP() << ":" << tCaster->getHP() << ":" << tCaster->getChannels();
        }

        Event e(inEvt);
        return reject(e);
      }
    }

    // prepare the response event
    Event resp(inEvt);
    resp.setProperty("Spell", lSpell->getUID());
    resp.setProperty("C", lSpell->getCaster()->getUID());
    if (lSpell->requiresTarget())
      resp.setProperty("T", lSpell->getTarget()->getUID());

		// dispatch to Lua
		/*lua_getfield(lua_, LUA_GLOBALSINDEX, "process_spell");
		if(!lua_isfunction(lua_, 1))
		{
			log_->errorStream() << "could not find Lua event processor!";
			lua_pop(lua_,1);
      Event e(inEvt);
      return reject(e);
		}

    log_->debugStream() << "\t things are looking good, passing to lua: "
      << ", cost: " << lSpell->getCostWP() << ":" << lSpell->getCostHP() << ":"
      << lSpell->getCostChannels();

		tolua_pushusertype(lua_,(void*)lCaster,"Pixy::Entity");
    tolua_pushusertype(lua_,(void*)lTarget,"Pixy::Entity");
		tolua_pushusertype(lua_,(void*)lSpell,"Pixy::Spell");
		tolua_pushusertype(lua_,(void*)&inEvt,"Pixy::Event");
		try {
			lua_call(lua_, 4, 1);
		} catch (std::exception& e) {
			log_->errorStream() << "Lua Handler: " << e.what();
		}

		bool result = lua_toboolean(lua_, lua_gettop(lua_));

		lua_remove(lua_, lua_gettop(lua_));*/
    bool result = pass_to_lua(
      "Spells.onCastSpell",
      3,
      "Pixy::Entity", lCaster,
      "Pixy::Entity", lTarget,
      "Pixy::Spell", lSpell);

    log_->debugStream() << "\t back from lua: "
      << ", cost: " << lSpell->getCostWP() << ":" << lSpell->getCostHP() << ":"
      << lSpell->getCostChannels();

    // if the spell cast was successful, we first broadcast the command to
    // the clients, then detach the spell from the caster, and finally
    // we apply any resource changes to the caster and broadcast them too
    if (result) {

      // broadcast the CastSpell event to players, confirming it
      {
        resp.Feedback = EventFeedback::Ok;
        broadcast(resp);
      }

      // update the caster stats and broadcast them
      {
        Event evt(EventUID::Unassigned, EventFeedback::Ok);
        evt.setProperty("UID", lCaster->getUID());

        if (lCaster->getRank() == PUPPET)
        {
          Puppet* tCaster = static_cast<Puppet*>(lCaster);
          evt.UID = EventUID::UpdatePuppet;
          // apply WP cost, if any
          if (lSpell->getCostWP() > 0) {
            tCaster->setWP(tCaster->getWP() - lSpell->getCostWP());
            evt.setProperty("WP", tCaster->getWP());
            log_->debugStream()
              << tCaster->getName() << " paid " << lSpell->getCostWP() << " wp,"
              << " and now has " << tCaster->getWP() << " wp.";
          }
          // apply the Channels cost, if any
          if (lSpell->getCostChannels() > 0) {
            tCaster->setChannels(tCaster->getChannels() - lSpell->getCostChannels());
            evt.setProperty("Channels", tCaster->getChannels());
            log_->debugStream()
              << tCaster->getName() << " paid " << lSpell->getCostChannels() << " channels,"
              << " and now has " << tCaster->getChannels() << " channels.";
          }
        } else
          evt.UID = EventUID::UpdateUnit;

        // apply HP cost, if any
        if (lSpell->getCostHP() > 0) {
          lCaster->setHP(lCaster->getHP() - lSpell->getCostHP());
          evt.setProperty("HP", lCaster->getHP());
          log_->debugStream()
              << lCaster->getName() << " paid " << lSpell->getCostHP() << " hp,"
              << " and now has " << lCaster->getHP() << " hp.";
        }

        broadcast(evt);
      }

      // don't delete the spell object if it's a buff
      lCaster->detachSpell(lSpell->getUID(), lSpell->getDuration() == 0);

    } else {
      // we reject the request
      //Event e(inEvt);
      resp.Feedback = EventFeedback::Error;
      return reject(resp);
    }

    lSpell = 0;
    lCaster = 0;
    lTarget = 0;

		//return result;
	}