Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
jdrueckert committed Nov 18, 2020
2 parents 221de96 + 5e7ce9b commit 090d7bc
Show file tree
Hide file tree
Showing 12 changed files with 320 additions and 141 deletions.
5 changes: 5 additions & 0 deletions assets/prefabs/damageTypes/maxHealthReductionDamage.prefab
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"DisplayName": {
"name": "MaxHealthReduction"
}
}
4 changes: 2 additions & 2 deletions module.txt
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{
"id" : "Health",
"version" : "1.0.1",
"version" : "1.1.0",
"isReleaseManaged": true,
"author" : "The Terasology Foundation",
"displayName" : "Health",
"description" : "This module provides basic implementation of Health",
"dependencies" : [
{ "id": "ModuleTestingEnvironment", "minVersion": "0.1.0", "optional":true },
{ "id": "ModuleTestingEnvironment", "minVersion": "0.2.0", "optional": true },
{ "id": "CoreAssets", "minVersion": "2.0.1" }
],
"serverSideOnly" : false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.terasology.logic.health.event.OnDamagedEvent;
import org.terasology.logic.health.event.OnFullyHealedEvent;
import org.terasology.logic.location.LocationComponent;
import org.terasology.math.JomlUtil;
import org.terasology.math.TeraMath;
import org.terasology.math.geom.Vector2f;
import org.terasology.math.geom.Vector3f;
Expand Down Expand Up @@ -170,7 +171,7 @@ private void createBlockParticleEffect(BlockFamily family, Vector3f location) {
spriteComponent.texture = terrainTexture.get();
spriteComponent.textureSize.set(spriteSize, spriteSize);

final List<Vector2f> offsets = computeOffsets(blockAppearance, particleScale);
final List<org.joml.Vector2f> offsets = computeOffsets(blockAppearance, particleScale);

TextureOffsetGeneratorComponent textureOffsetGeneratorComponent = builder.getComponent(TextureOffsetGeneratorComponent.class);
textureOffsetGeneratorComponent.validOffsets.addAll(offsets);
Expand All @@ -187,7 +188,7 @@ private void createBlockParticleEffect(BlockFamily family, Vector3f location) {
*
* @return a list of random offsets sampled from all block parts
*/
private List<Vector2f> computeOffsets(BlockAppearance blockAppearance, float scale) {
private List<org.joml.Vector2f> computeOffsets(BlockAppearance blockAppearance, float scale) {
final float relativeTileSize = worldAtlas.getRelativeTileSize();
final int absoluteTileSize = worldAtlas.getTileSize();
final float pixelSize = relativeTileSize / absoluteTileSize;
Expand All @@ -197,7 +198,7 @@ private List<Vector2f> computeOffsets(BlockAppearance blockAppearance, float sca

return baseOffsets.flatMap(baseOffset ->
IntStream.range(0, 8).boxed().map(i ->
new Vector2f(baseOffset).add(random.nextInt(absoluteTileSize - spriteWidth) * pixelSize, random.nextInt(absoluteTileSize - spriteWidth) * pixelSize)
new org.joml.Vector2f(JomlUtil.from(baseOffset)).add(random.nextInt(absoluteTileSize - spriteWidth) * pixelSize, random.nextInt(absoluteTileSize - spriteWidth) * pixelSize)
)
).collect(Collectors.toList());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,9 @@
/*
* Copyright 2019 MovingBlocks
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Copyright 2020 The Terasology Foundation
// SPDX-License-Identifier: Apache-2.0
package org.terasology.logic.health;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.terasology.audio.StaticSound;
import org.terasology.audio.events.PlaySoundEvent;
import org.terasology.audio.events.PlaySoundForOwnerEvent;
Expand All @@ -32,9 +21,12 @@
import org.terasology.logic.characters.events.AttackEvent;
import org.terasology.logic.characters.events.HorizontalCollisionEvent;
import org.terasology.logic.characters.events.VerticalCollisionEvent;
import org.terasology.logic.delay.DelayManager;
import org.terasology.logic.delay.DelayedActionTriggeredEvent;
import org.terasology.logic.health.event.ActivateRegenEvent;
import org.terasology.logic.health.event.BeforeDamagedEvent;
import org.terasology.logic.health.event.DamageSoundComponent;
import org.terasology.logic.health.event.DeactivateRegenEvent;
import org.terasology.logic.health.event.DoDamageEvent;
import org.terasology.logic.health.event.DoRestoreEvent;
import org.terasology.logic.health.event.OnDamagedEvent;
Expand All @@ -50,25 +42,35 @@
* horizontal and vertical crashes of entities with HealthComponents.
* <p>
* Logic flow for damage:
* - OnDamageEvent
* - BeforeDamageEvent
* - (HealthComponent saved)
* - OnDamagedEvent
* - DestroyEvent (if no health)
* <ul>
* <li>{@link DoDamageEvent}</li>
* <li>{@link BeforeDamagedEvent}</li>
* <li>{@link HealthComponent} is saved</li>
* <li>{@link OnDamagedEvent}</li>
* <li>{@link DestroyEvent} (if reaching 0 health)</li>
* </ul>
*/
@RegisterSystem(RegisterMode.AUTHORITY)
public class DamageAuthoritySystem extends BaseComponentSystem {

private static final Logger logger = LoggerFactory.getLogger(DamageAuthoritySystem.class);

private static final String DELAYED_REGEN_ACTIVATION = "DamageAuthoritySystem:activateRegenEvent";

@In
private Time time;

@In
private DelayManager delayManager;

private Random random = new FastRandom();


/**
* Override the default behavior for an attack, causing it damage as opposed to just destroying it or doing nothing.
* Override the default behavior for an attack, causing it damage as opposed to just destroying it or doing
* nothing.
*
* @param event Attack event sent on targetEntity.
* @param event Attack event sent on targetEntity.
* @param targetEntity The entity which is attacked.
*/
@ReceiveEvent(components = HealthComponent.class, netFilter = RegisterMode.AUTHORITY)
Expand All @@ -93,7 +95,8 @@ public static void damageEntity(AttackEvent event, EntityRef targetEntity) {
event.consume();
}

private void doDamage(EntityRef entity, int damageAmount, Prefab damageType, EntityRef instigator, EntityRef directCause) {
private void doDamage(EntityRef entity, int damageAmount, Prefab damageType, EntityRef instigator,
EntityRef directCause) {
HealthComponent health = entity.getComponent(HealthComponent.class);
CharacterMovementComponent characterMovementComponent = entity.getComponent(CharacterMovementComponent.class);
boolean ghost = false;
Expand All @@ -103,32 +106,54 @@ private void doDamage(EntityRef entity, int damageAmount, Prefab damageType, Ent
if ((health != null) && !ghost) {
int cappedDamage = Math.min(health.currentHealth, damageAmount);
health.currentHealth -= cappedDamage;
entity.send(new ActivateRegenEvent());
entity.saveComponent(health);
entity.send(new OnDamagedEvent(damageAmount, cappedDamage, damageType, instigator));
if (health.currentHealth == 0 && health.destroyEntityOnNoHealth) {
entity.send(new DestroyEvent(instigator, directCause, damageType));
}
scheduleRegenEvent(entity, health.waitBeforeRegen);
}
}

private void scheduleRegenEvent(EntityRef entity, float delayInSeconds) {
// deactivate base regen because entity was damaged
entity.send(new DeactivateRegenEvent());
// reset timer for activating the base regen on the entity
if (delayManager.hasDelayedAction(entity, DELAYED_REGEN_ACTIVATION)) {
logger.debug("Canceling previous delayed regen event");
delayManager.cancelDelayedAction(entity, DELAYED_REGEN_ACTIVATION);
}
long delayInMs = Math.round(delayInSeconds * 1000);
logger.debug("Scheduling delayed regen event with delay '{}'", delayInMs);
delayManager.addDelayedAction(entity, DELAYED_REGEN_ACTIVATION, delayInMs);
}

@ReceiveEvent
public void onDelayedRegenActivation(DelayedActionTriggeredEvent event, EntityRef entity, HealthComponent health) {
if (event.getActionId().equals(DELAYED_REGEN_ACTIVATION)) {
entity.send(new ActivateRegenEvent(health.regenRate));
}
}

/**
* Handles DoDamageEvent to inflict damage to entity with HealthComponent.
*
* @param event DoDamageEvent causing the damage on the entity.
* @param event DoDamageEvent causing the damage on the entity.
* @param entity The entity which is damaged.
*/
@ReceiveEvent
public void onDamage(DoDamageEvent event, EntityRef entity) {
checkDamage(entity, event.getAmount(), event.getDamageType(), event.getInstigator(), event.getDirectCause());
}

private void checkDamage(EntityRef entity, int amount, Prefab damageType, EntityRef instigator, EntityRef directCause) {
private void checkDamage(EntityRef entity, int amount, Prefab damageType, EntityRef instigator,
EntityRef directCause) {
// Ignore 0 damage
if (amount == 0) {
return;
}
BeforeDamagedEvent beforeDamage = entity.send(new BeforeDamagedEvent(amount, damageType, instigator, directCause));
BeforeDamagedEvent beforeDamage = entity.send(new BeforeDamagedEvent(amount, damageType, instigator,
directCause));
if (!beforeDamage.isConsumed()) {
int damageAmount = TeraMath.floorToInt(beforeDamage.getResultValue());
if (damageAmount > 0) {
Expand All @@ -142,8 +167,8 @@ private void checkDamage(EntityRef entity, int amount, Prefab damageType, Entity
/**
* Handles damage sound on inflicting damage to entity.
*
* @param event OnDamagedEvent triggered when entity is damaged.
* @param entity Entity which is damaged.
* @param event OnDamagedEvent triggered when entity is damaged.
* @param entity Entity which is damaged.
* @param characterSounds Component having sound settings.
*/
@ReceiveEvent
Expand Down Expand Up @@ -176,7 +201,7 @@ public void onDamaged(OnDamagedEvent event, EntityRef entity, CharacterSoundComp
/**
* Causes damage to entity when fallingDamageSpeedThreshold is breached.
*
* @param event VerticalCollisionEvent sent when falling speed threshold is crossed.
* @param event VerticalCollisionEvent sent when falling speed threshold is crossed.
* @param entity The entity which is damaged due to falling.
*/
@ReceiveEvent
Expand All @@ -189,7 +214,7 @@ public void onLand(VerticalCollisionEvent event, EntityRef entity, HealthCompone
/**
* Inflicts damage to entity if horizontalDamageSpeedThreshold is breached.
*
* @param event HorizontalCollisionEvent sent when "falling horizontally".
* @param event HorizontalCollisionEvent sent when "falling horizontally".
* @param entity Entity which is damaged on "horizontal fall".
*/
@ReceiveEvent
Expand All @@ -213,13 +238,14 @@ private void highSpeedDamage(float speed, EntityRef entity, float threshold, flo
/**
* Plays landing sound on crashing horizontally.
*
* @param event HorizontalCollisionEvent sent when "falling horizontally".
* @param entity Entity which is damaged on "horizontal fall".
* @param event HorizontalCollisionEvent sent when "falling horizontally".
* @param entity Entity which is damaged on "horizontal fall".
* @param characterSounds For getting the sound to be played on crash.
* @param healthComponent To play sound only when threshold speed is crossed.
*/
@ReceiveEvent
public void onCrash(HorizontalCollisionEvent event, EntityRef entity, CharacterSoundComponent characterSounds, HealthComponent healthComponent) {
public void onCrash(HorizontalCollisionEvent event, EntityRef entity, CharacterSoundComponent characterSounds,
HealthComponent healthComponent) {
Vector3f horizVelocity = new Vector3f(event.getVelocity());
horizVelocity.y = 0;
float velocity = horizVelocity.length();
Expand All @@ -239,7 +265,7 @@ public void onCrash(HorizontalCollisionEvent event, EntityRef entity, CharacterS
/**
* Reduces the baseDamage of BeforeDamagedEvent if DamageResistComponent is added.
*
* @param event BeforeDamagedEvent sent before inflicting damage
* @param event BeforeDamagedEvent sent before inflicting damage
* @param entity Entity which suffered some type of damage
*/
@ReceiveEvent
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright 2020 The Terasology Foundation
// SPDX-License-Identifier: Apache-2.0

package org.terasology.logic.health;

import org.terasology.entitySystem.entity.EntityRef;
import org.terasology.entitySystem.event.EventPriority;
import org.terasology.entitySystem.event.ReceiveEvent;
import org.terasology.entitySystem.prefab.Prefab;
import org.terasology.entitySystem.prefab.PrefabManager;
import org.terasology.entitySystem.systems.BaseComponentSystem;
import org.terasology.entitySystem.systems.RegisterMode;
import org.terasology.entitySystem.systems.RegisterSystem;
import org.terasology.logic.health.event.ChangeMaxHealthEvent;
import org.terasology.logic.health.event.DoDamageEvent;
import org.terasology.logic.health.event.MaxHealthChangedEvent;
import org.terasology.nui.widgets.UIIconBar;
import org.terasology.registry.In;
import org.terasology.rendering.nui.NUIManager;

@RegisterSystem(value = RegisterMode.AUTHORITY)
public class HealthAuthoritySystem extends BaseComponentSystem {
@In
NUIManager nuiManager;
@In
PrefabManager prefabManager;

/**
* Sends out an immutable notification event when maxHealth of a character is changed.
*/
@ReceiveEvent(priority = EventPriority.PRIORITY_TRIVIAL)
public void changeMaxHealth(ChangeMaxHealthEvent event, EntityRef player, HealthComponent health) {
int oldMaxHealth = health.maxHealth;
health.maxHealth = (int) event.getResultValue();
Prefab maxHealthReductionDamagePrefab = prefabManager.getPrefab("Health:maxHealthReductionDamage");
player.send(new DoDamageEvent(Math.max(health.currentHealth - health.maxHealth, 0),
maxHealthReductionDamagePrefab));
player.send(new MaxHealthChangedEvent(oldMaxHealth, health.maxHealth));
player.saveComponent(health);
}

/**
* Reacts to the {@link MaxHealthChangedEvent} notification event. Is responsible for the change in maximum number
* of icons in the Health Bar UI.
*/
@ReceiveEvent
public void onMaxHealthChanged(MaxHealthChangedEvent event, EntityRef player) {
UIIconBar healthBar = nuiManager.getHUD().find("healthBar", UIIconBar.class);
healthBar.setMaxIcons(event.getNewValue() / 10);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

import org.terasology.entitySystem.Component;
import org.terasology.network.Replicate;
import org.terasology.rendering.nui.properties.TextField;
import org.terasology.nui.properties.TextField;

/**
* Provides Health to entity attached with HealthComponent. Contains the parameters
Expand Down
Loading

0 comments on commit 090d7bc

Please sign in to comment.