int TangibleObjectImplementation::inflictDamage(TangibleObject* attacker, int damageType, float damage, bool destroy, bool notifyClient) {
	if(hasAntiDecayKit())
		return 0;

	float newConditionDamage = conditionDamage + damage;

	if (!destroy && newConditionDamage >= maxCondition)
		newConditionDamage = maxCondition - 1;
	else if (newConditionDamage >= maxCondition)
		newConditionDamage = maxCondition;

	setConditionDamage(newConditionDamage, notifyClient);

	if (attacker->isCreatureObject()) {
		CreatureObject* creature = attacker->asCreatureObject();

		if (damage > 0 && attacker != asTangibleObject())
			getThreatMap()->addDamage(creature, (uint32)damage);
	}

	if (newConditionDamage >= maxCondition)
		notifyObjectDestructionObservers(attacker, newConditionDamage);

	return 0;
}
void TangibleObjectImplementation::notifyLoadFromDatabase() {
	SceneObjectImplementation::notifyLoadFromDatabase();

	for (int i = 0; i < activeAreas.size(); ++i) {
		activeAreas.get(i)->notifyExit(asTangibleObject());
	}

	activeAreas.removeAll();

	if (hasAntiDecayKit()) {
		AntiDecayKit* adk = antiDecayKitObject.castTo<AntiDecayKit*>();

		if (adk != NULL && !adk->isUsed()) {
			Locker locker(adk);

			adk->setUsed(true);
		}
	}
}
void WeaponObjectImplementation::decay(CreatureObject* user) {
	if (_this.getReferenceUnsafeStaticCast() == user->getSlottedObject("default_weapon") || user->isAiAgent() || hasAntiDecayKit()) {
		return;
	}

	int roll = System::random(100);
	int chance = 5;

	if (hasPowerup())
		chance += 10;

	if (roll < chance) {
		if (isJediWeapon()) {
			ManagedReference<SceneObject*> saberInv = getSlottedObject("saber_inv");

			if (saberInv == NULL)
				return;

			// TODO: is this supposed to be every crystal, or random crystal(s)?
			for (int i = 0; i < saberInv->getContainerObjectsSize(); i++) {
				ManagedReference<LightsaberCrystalComponent*> crystal = saberInv->getContainerObject(i).castTo<LightsaberCrystalComponent*>();

				if (crystal != NULL) {
					crystal->inflictDamage(crystal, 0, 1, true, true);
				}
			}
		} else {
			inflictDamage(_this.getReferenceUnsafeStaticCast(), 0, 1, true, true);

			if (((float)conditionDamage - 1 / (float)maxCondition < 0.75) && ((float)conditionDamage / (float)maxCondition > 0.75))
				user->sendSystemMessage("@combat_effects:weapon_quarter");
			if (((float)conditionDamage - 1 / (float)maxCondition < 0.50) && ((float)conditionDamage / (float)maxCondition > 0.50))
				user->sendSystemMessage("@combat_effects:weapon_half");
		}
	}
}
void WeaponObjectImplementation::fillAttributeList(AttributeListMessage* alm, CreatureObject* object) {
	TangibleObjectImplementation::fillAttributeList(alm, object);

	bool res = isCertifiedFor(object);

	if (res) {
		alm->insertAttribute("weapon_cert_status", "Yes");
	} else {
		alm->insertAttribute("weapon_cert_status", "No");
	}

	/*if (usesRemaining > 0)
		alm->insertAttribute("count", usesRemaining);*/

	for(int i = 0; i < wearableSkillMods.size(); ++i) {
		String key = wearableSkillMods.elementAt(i).getKey();
		String statname = "cat_skill_mod_bonus.@stat_n:" + key;
		int value = wearableSkillMods.get(key);

		if (value > 0)
			alm->insertAttribute(statname, value);
	}

	String ap;

	switch (armorPiercing) {
	case NONE:
		ap = "None";
		break;
	case LIGHT:
		ap = "Light";
		break;
	case MEDIUM:
		ap = "Medium";
		break;
	case HEAVY:
		ap = "Heavy";
		break;
	default:
		ap = "Unknown";
		break;
	}

	alm->insertAttribute("wpn_armor_pierce_rating", ap);

	alm->insertAttribute("wpn_attack_speed", Math::getPrecision(getAttackSpeed(), 1));

	if (getDamageRadius() != 0.0f)
		alm->insertAttribute("area", Math::getPrecision(getDamageRadius(), 0));

	//Damage Information
	StringBuffer dmgtxt;

	switch (damageType) {
	case KINETIC:
		dmgtxt << "Kinetic";
		break;
	case ENERGY:
		dmgtxt << "Energy";
		break;
	case ELECTRICITY:
		dmgtxt << "Electricity";
		break;
	case STUN:
		dmgtxt << "Stun";
		break;
	case BLAST:
		dmgtxt << "Blast";
		break;
	case HEAT:
		dmgtxt << "Heat";
		break;
	case COLD:
		dmgtxt << "Cold";
		break;
	case ACID:
		dmgtxt << "Acid";
		break;
	case LIGHTSABER:
		dmgtxt << "Lightsaber";
		break;
	default:
		dmgtxt << "Unknown";
		break;
	}

	alm->insertAttribute("damage.wpn_damage_type", dmgtxt);

	float minDmg = round(getMinDamage());
	float maxDmg = round(getMaxDamage());

	alm->insertAttribute("damage.wpn_damage_min", minDmg);

	alm->insertAttribute("damage.wpn_damage_max", maxDmg);

	StringBuffer woundsratio;

	float wnd = round(10 * getWoundsRatio()) / 10.0f;

	woundsratio << wnd << "%";

	alm->insertAttribute("damage.wpn_wound_chance", woundsratio);

	//Accuracy Modifiers
	StringBuffer pblank;
	if (getPointBlankAccuracy() >= 0)
		pblank << "+";

	pblank << getPointBlankAccuracy() << " @ " << getPointBlankRange() << "m";
	alm->insertAttribute("cat_wpn_rangemods.wpn_range_zero", pblank);

	StringBuffer ideal;
	if (getIdealAccuracy() >= 0)
		ideal << "+";

	ideal << getIdealAccuracy() << " @ " << getIdealRange() << "m";
	alm->insertAttribute("cat_wpn_rangemods.wpn_range_mid", ideal);

	StringBuffer maxrange;
	if (getMaxRangeAccuracy() >= 0)
		maxrange << "+";

	maxrange << getMaxRangeAccuracy() << " @ " << getMaxRange() << "m";
	alm->insertAttribute("cat_wpn_rangemods.wpn_range_max", maxrange);

	//Special Attack Costs
	alm->insertAttribute("cat_wpn_attack_cost.health", getHealthAttackCost());

	alm->insertAttribute("cat_wpn_attack_cost.action", getActionAttackCost());

	alm->insertAttribute("cat_wpn_attack_cost.mind", getMindAttackCost());

	//Anti Decay Kit
	if(hasAntiDecayKit()){
		alm->insertAttribute("@veteran_new:antidecay_examine_title", "@veteran_new:antidecay_examine_text");
	}

	// Force Cost
	if (getForceCost() > 0)
		alm->insertAttribute("forcecost", (int)getForceCost());

	for (int i = 0; i < getNumberOfDots(); i++) {

			String dt;

			switch (getDotType(i)) {
			case 1:
				dt = "Poison";
				break;
			case 2:
				dt = "Disease";
				break;
			case 3:
				dt = "Fire";
				break;
			case 4:
				dt = "Bleeding";
				break;
			default:
				dt = "Unknown";
				break;
			}

			StringBuffer type;
			type << "cat_wpn_dot_0" << i << ".wpn_dot_type";
			alm->insertAttribute(type.toString(), dt);

			String da;

			switch (getDotAttribute(i)) {
			case 0:
				da = "Health";
				break;
			case 1:
				da = "Strength";
				break;
			case 2:
				da = "Constitution";
				break;
			case 3:
				da = "Action";
				break;
			case 4:
				da = "Quickness";
				break;
			case 5:
				da = "Stamina";
				break;
			case 6:
				da = "Mind";
				break;
			case 7:
				da = "Focus";
				break;
			case 8:
				da = "Willpower";
				break;
			default:
				da = "Unknown";
				break;
			}

			StringBuffer attrib;
			attrib << "cat_wpn_dot_0" << i << ".wpn_dot_attrib";
			alm->insertAttribute(attrib.toString(), da);

			StringBuffer str;
			str << "cat_wpn_dot_0" << i << ".wpn_dot_strength";
			alm->insertAttribute(str.toString(), getDotStrength(i));

			StringBuffer dotDur;
			dotDur << getDotDuration(i) << "s";
			StringBuffer dur;
			dur << "cat_wpn_dot_0" << i << ".wpn_dot_duration";
			alm->insertAttribute(dur.toString(), dotDur);

			StringBuffer dotPot;
			dotPot << getDotPotency(i) << "%";
			StringBuffer pot;
			pot << "cat_wpn_dot_0" << i << ".wpn_dot_potency";
			alm->insertAttribute(pot.toString(), dotPot);

			StringBuffer use;
			use << "cat_wpn_dot_0" << i << ".wpn_dot_uses";
			alm->insertAttribute(use.toString(), getDotUses(i));
		}

	if(hasPowerup())
		powerupObject->fillWeaponAttributeList(alm, _this.getReferenceUnsafeStaticCast());

	if (sliced == 1)
		alm->insertAttribute("wpn_attr", "@obj_attr_n:hacked1");

}