# Team Gifts

**URL:** https://heroiclabs.com/docs/hiro/concepts/teams/gifts/
**Keywords:** gifts, teams
**Categories:** hiro, gifts, teams

---


# Team Gifts

Multiplayer games thrive on collective momentum, the feeling that your team is building toward something together.

Team Gifts give players a shared goal to chase after, along with a limited window to get it done. Every team member visibly pushes progress forward; the team is rewarded when they hit their goals, with the biggest payoff going to the players who contributed the most. The result is urgency, coordination, and a reason to log into your game before the window closes.

## How Team Gifts work

Team Gifts run in repeating iterations, each defined by a schedule you control. Within each iteration, there's a contribution window: a period during which members can add to the team's shared progress counter. When the team crosses contribution milestones, reward tiers unlock. Members then claim their rewards individually, with contributors and non-contributors potentially receiving different payouts.

Think of it like a shared loot pool with escalating prizes. The team only hits the big reward if enough people contribute, but even members who sat out can receive something smaller if you choose to configure it that way.

The key moving parts are:

- **Iterations:** Each iteration of a Team Gifts event has a preconfigured start and end time, along with the option to reset on a schedule. Each iteration is independent and has its own progress tracking and rewards.
- **Contribution windows:** The limited amount of time within an iteration during which members can contribute. Once it closes, progress is locked and members can claim their rewards.
- **Reward milestones:** Rather than a single finish line, gifts have multiple reward thresholds. When the team crosses a threshold (for example, 25, 50, or 100 total contributions), that reward unlocks for all members to claim.
- **Contributor vs non-contributor rewards:** Each tier can define different payouts depending on whether a member contributed or not. This incentivizes participation while still keeping passive members engaged. A contributor is someone who contributed to the gift at least once during the _entire window_.

## Understanding contribution windows

The contribution window is what separates Team Gifts from other systems that just use a simple progress meter. Without a window, players can contribute at any time: there's no reason to coordinate, no urgency, and no moment when the team _wins together_.

When you configure a contribution window, you create a defined period within the iteration where contribution is possible. That time pressure is the design mechanism that produces coordinated play sessions, the feeling of a shared event, and meaningful goals for teams to rally around.

## Team Gifts vs Team Achievements

Team Gifts are similar to [Team Achievements](../achievements/) in that they are both goal-oriented systems, but serve a distinct design purpose.

Team Achievements are about completing goals. Goals can depend on each other, progress is shared, and the structure can be as complex as a branching quest tree. There's no inherent time pressure, and the team typically works through one goal at a time.

Team Gifts are about filling a shared progress bar before the clock runs out. The structure is flatter, one counter, multiple thresholds, and the time constraint is the point. The player feeling is fundamentally different: not _"let's finish this objective"_ but _"let's push together before the round ends."_

{{< table name="hiro.concepts.teams.gifts.gifts-vs-achievements" >}}

## Common use cases

Team Gifts work best for short, repeatable events where time pressure and collective action are the core experience.

### Weekly guild treasury

Members deposit currency into a guild treasury throughout the week. As the treasury fills, milestone rewards unlock for the whole guild. Contributors earn a larger payout at each tier; non-contributors receive a smaller share, keeping them engaged without undermining the incentive to deposit. In order to keep things fair, however, the top milestone reserves its reward exclusively for contributors.

**How it works**: The treasury resets every Monday. A five-day contribution window (`duration_sec: 432000`) closes deposits on Friday, giving members the weekend to claim rewards. Each member is capped at 25 deposits (`max_contributor_count: 25`) so no single player can carry the guild to a milestone alone. A small `contribution_cost` per deposit makes each one a deliberate choice. Milestones unlock at 100, 300, and 500 total deposits with escalating payouts.

**Example configuration**

```json
"guild_treasury": {
  "reset_schedule": "0 0 * * 1",
  "duration_sec": 432000, // how long the contribution window lasts
  "max_count": 500, // how many contributions total can be made
  "max_contributor_count": 25, // how many contributions per member can be made
  "contribution_cost": { // the cost to make a contribution to the gift
    "currencies": {
      "GuildCoins": {
        "min": 10
      }
    }
  },
  "rewards": [
    {
      "min_count": 100, // the number of contributions needed for this reward milestone
      "contributor_reward": {
        "currencies": {
          "GuildCoins": {
            "min": 50
          }
        }
      },
      "noncontributor_reward": {
        "currencies": {
          "GuildCoins": {
            "min": 10
          }
        }
      }
    },
    {
      "min_count": 300,
      "contributor_reward": {
        "currencies": {
          "GuildCoins": {
            "min": 150
          }
        }
      },
      "noncontributor_reward": {
        "currencies": {
          "GuildCoins": {
            "min": 30
          }
        }
      }
    },
    {
      "min_count": 500,
      "contributor_reward": { // only contributors earn this final reward milestone
        "items": {
          "GuildCrest": {
            "min": 1
          }
        }
      }
    }
  ]
}
```

### Weekend boss raid

A boss encounter in your game opens Friday night. The team has 48 hours to deal as much damage as possible by contributing resources to the fight, then the rest of the week to collect loot. The short contribution window creates urgency and rallies everyone together over the weekend, while the extended claiming period gives everyone time to collect their loot and take a breather.

<!-- TODO: We've mentioned hooks but we don't have hooks documented, it needs to go into the server framework guides -->

**How it works**: Specifying `duration_sec: 172800` closes contributions after a 48-hour window while the iteration runs for a full week. All team members can claim for the remaining five days of the week, with contributors earning themselves a raid chest (defined in your [Inventory](../../inventory/) system) and non-contributors receiving a consolation prize. To customize the rewards further, use server-side hooks like `onGiftContributeReward` or `onGiftClaimReward` to modify payouts dynamically.

**Example configuration**

```json
"boss_encounter": {
  "reset_schedule": "0 0 * * 5",
  "duration_sec": 172800,
  "rewards": [
    {
      "min_count": 400,
      "contributor_reward": {
        "items": {
          "RaidChest": {
            "min": 1
          }
        }
      },
      "noncontributor_reward": {
        "currencies": {
          "GalacticCredits": {
            "min": 150
          }
        }
      }
    }
  ]
}
```

### Seasonal community drive

During a themed event (New Year's, winter festival, or anniversary), the team collects event-specific tokens to unlock limited-time cosmetics and items. The seasonal framing gives the event narrative weight, and the contribution window creates a defined push period during the event, possibly alongside other events you may be running.

**How it works**: A two-week iteration runs for the duration of the seasonal event. A 10-day contribution window (`duration_sec: 864000`) closes token collection four days before the iteration ends, leaving a final weekend for members to claim rewards. Each member can contribute up to 50 tokens. Milestones unlock at 200, 500, and 1,000 total contributions, with themed rewards at each tier. Contributors earn exclusive cosmetics; non-contributors receive a smaller event currency payout.

**Example configuration**

```json
"winter_festival_drive": {
  "reset_schedule": "0 0 1,15 * *",
  "duration_sec": 864000,
  "max_count": 1000,
  "max_contributor_count": 50,
  "contribution_cost": {
    "currencies": {
      "FrostTokens": {
        "min": 1
      }
    }
  },
  "rewards": [
    {
      "min_count": 200,
      "contributor_reward": {
        "currencies": {
          "FrostTokens": {
            "min": 50
          }
        }
      },
      "noncontributor_reward": {
        "currencies": {
          "FrostTokens": {
            "min": 10
          }
        }
      }
    },
    {
      "min_count": 500,
      "contributor_reward": {
        "items": {
          "IceLantern": {
            "min": 1
          }
        }
      },
      "noncontributor_reward": {
        "currencies": {
          "FrostTokens": {
            "min": 25
          }
        }
      }
    },
    {
      "min_count": 1000,
      "contributor_reward": {
        "items": {
          "WinterCrown": {
            "min": 1
          }
        }
      }
    }
  ]
}
```

## Edge cases

These behaviors can be non-obvious the first time you encounter them.

**A contribution of zero is submitted.** The server defaults it to one. This ensures each contribution call records at least one unit of progress.

**A member tries to contribute more than their limit.** The server caps the contribution to whatever the member's remaining allowance is. It won't error out, it'll just record as much as is permitted.

**A member hits multiple tiers before claiming.** When they claim, all newly available tiers are returned at once. They don't need to claim each tier individually.

**A member never contributed.** If a tier defines a non-contributor reward, that member can still claim it once the team hits the threshold. If no non-contributor reward is defined, that tier grants them nothing.

**The gift resets before a member claims.** Unclaimed rewards from a previous iteration expire when the new iteration starts. There's no carryover.

**A claim is submitted with the wrong end time.** Claims are tied to a specific iteration by end time. A mismatch causes the claim to be rejected.

## Configuring Team Gifts

**Gifts Config**
{{< table name="hiro.concepts.teams.gifts.gifts-config" >}}

**Individual Gift Config**

Each gift is defined by a unique ID (the key) and its configuration properties:

{{< table name="hiro.concepts.teams.gifts.individual-gifts-config" >}}

**Gift Reward Tiers**

{{< table name="hiro.concepts.teams.gifts.gift-reward-tier" >}} 

### Example: Team Gifts JSON

The JSON schema defines a `gifts` object which contains individual gift definitions. Configure as many gifts as you need and tune schedules to match your live ops cadence.

```json
{
  // ... other Team configs
  "gifts": {
    "gifts": {
      "weekend_drive": {
        "name": "Weekend Drive",
        "description": "Contribute together to unlock weekend rewards",
        "category": "events",
        "reset_schedule": "0 0 * * *",
        "duration_sec": 172800,
        "max_count": 200,
        "max_contributor_count": 20,
        "contribution_cost": {
          "guaranteed": {
            "currencies": { "team_tokens": { "min": 5 } }
          }
        },
        "contribution_reward": {
          "guaranteed": {
            "currencies": { "team_tokens": { "min": 2 } }
          }
        },
        "rewards": [
          {
            "min_count": 25,
            "contributor_reward": {
              "guaranteed": {
                "items": { "boost_small": { "min": 1 } }
              }
            },
            "noncontributor_reward": {
              "guaranteed": {
                "currencies": { "coins": { "min": 100 } }
              }
            }
          },
          {
            "min_count": 100,
            "contributor_reward": {
              "guaranteed": {
                "items": { "boost_large": { "min": 1 } }
              }
            }
          }
        ]
      }
    }
  }
}
```
