Skip to content
114 changes: 114 additions & 0 deletions api_v2/migrations/0071_convert_distance_fields_to_integer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# Generated by Django 5.2.9 on 2025-12-31 18:32

import django.core.validators
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('api_v2', '0070_merge_20251130_2152'),
]

operations = [
migrations.AlterField(
model_name='creature',
name='blindsight_range',
field=models.IntegerField(blank=True, help_text='Used to measure distance.', null=True, validators=[django.core.validators.MinValueValidator(0)]),
),
migrations.AlterField(
model_name='creature',
name='burrow',
field=models.IntegerField(blank=True, help_text='Used to measure distance.', null=True, validators=[django.core.validators.MinValueValidator(0)]),
),
migrations.AlterField(
model_name='creature',
name='climb',
field=models.IntegerField(blank=True, help_text='Used to measure distance.', null=True, validators=[django.core.validators.MinValueValidator(0)]),
),
migrations.AlterField(
model_name='creature',
name='darkvision_range',
field=models.IntegerField(blank=True, help_text='Used to measure distance.', null=True, validators=[django.core.validators.MinValueValidator(0)]),
),
migrations.AlterField(
model_name='creature',
name='fly',
field=models.IntegerField(blank=True, help_text='Used to measure distance.', null=True, validators=[django.core.validators.MinValueValidator(0)]),
),
migrations.AlterField(
model_name='creature',
name='normal_sight_range',
field=models.IntegerField(blank=True, help_text='Used to measure distance.', null=True, validators=[django.core.validators.MinValueValidator(0)]),
),
migrations.AlterField(
model_name='creature',
name='swim',
field=models.IntegerField(blank=True, help_text='Used to measure distance.', null=True, validators=[django.core.validators.MinValueValidator(0)]),
),
migrations.AlterField(
model_name='creature',
name='telepathy_range',
field=models.IntegerField(blank=True, help_text='Used to measure distance.', null=True, validators=[django.core.validators.MinValueValidator(0)]),
),
migrations.AlterField(
model_name='creature',
name='tremorsense_range',
field=models.IntegerField(blank=True, help_text='Used to measure distance.', null=True, validators=[django.core.validators.MinValueValidator(0)]),
),
migrations.AlterField(
model_name='creature',
name='truesight_range',
field=models.IntegerField(blank=True, help_text='Used to measure distance.', null=True, validators=[django.core.validators.MinValueValidator(0)]),
),
migrations.AlterField(
model_name='creature',
name='walk',
field=models.IntegerField(blank=True, help_text='Used to measure distance.', validators=[django.core.validators.MinValueValidator(0)]),
),
migrations.AlterField(
model_name='creatureactionattack',
name='long_range',
field=models.IntegerField(blank=True, help_text='Used to measure distance.', null=True, validators=[django.core.validators.MinValueValidator(0)]),
),
migrations.AlterField(
model_name='creatureactionattack',
name='range',
field=models.IntegerField(blank=True, help_text='Used to measure distance.', null=True, validators=[django.core.validators.MinValueValidator(0)]),
),
migrations.AlterField(
model_name='creatureactionattack',
name='reach',
field=models.IntegerField(blank=True, help_text='Used to measure distance.', null=True, validators=[django.core.validators.MinValueValidator(0)]),
),
migrations.AlterField(
model_name='size',
name='space_diameter',
field=models.IntegerField(blank=True, help_text='Used to measure distance.', null=True, validators=[django.core.validators.MinValueValidator(0)]),
),
migrations.AlterField(
model_name='spell',
name='range',
field=models.IntegerField(blank=True, help_text='Used to measure distance.', null=True, validators=[django.core.validators.MinValueValidator(0)]),
),
migrations.AlterField(
model_name='spell',
name='shape_size',
field=models.IntegerField(blank=True, help_text='Used to measure distance.', null=True, validators=[django.core.validators.MinValueValidator(0)]),
),
migrations.AlterField(
model_name='spellcastingoption',
name='shape_size',
field=models.IntegerField(blank=True, help_text='Used to measure distance.', null=True, validators=[django.core.validators.MinValueValidator(0)]),
),
migrations.AlterField(
model_name='weapon',
name='long_range',
field=models.IntegerField(blank=True, help_text='Used to measure distance.', null=True, validators=[django.core.validators.MinValueValidator(0)]),
),
migrations.AlterField(
model_name='weapon',
name='range',
field=models.IntegerField(blank=True, help_text='Used to measure distance.', null=True, validators=[django.core.validators.MinValueValidator(0)]),
),
]
4 changes: 2 additions & 2 deletions api_v2/models/abstracts.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,10 @@ def key_field():
)

def distance_field(null=True):
return models.FloatField(
return models.IntegerField(
null=null,
blank=True,
validators=[MinValueValidator(decimal.Decimal(0.0))],
validators=[MinValueValidator(0)],
help_text="Used to measure distance."
)

Expand Down
26 changes: 11 additions & 15 deletions api_v2/models/speed.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,25 @@ class HasSpeed(models.Model):

def get_fly(self):
if self.fly is None:
return 0.0
return 0
return self.fly

def get_burrow(self):
if self.burrow is None:
return 0.0
return 0
return self.burrow

def get_climb(self):
if self.climb is None:
return self.walk / 2 # Climb speed is half of walk speed.
return self.walk // 2 # Climb speed is half of walk speed (integer division)
return self.climb

def get_crawl(self):
return self.walk / 2
return self.walk // 2 # Integer division

def get_swim(self):
if self.swim is None:
return self.walk / 2 # Swim speed is half of walk speed.
return self.walk // 2 # Swim speed is half of walk speed (integer division)
return self.swim

def get_unit(self):
Expand Down Expand Up @@ -85,17 +85,13 @@ def get_speed(self):
fields={
# todo: model typed as any
"unit": serializers.StringRelatedField(),
# todo: model typed as any
"walk": serializers.StringRelatedField(),
# todo: model typed as any
"crawl": serializers.StringRelatedField(),
"walk": serializers.IntegerField(),
"crawl": serializers.IntegerField(),
"hover": serializers.BooleanField(),
"fly": serializers.FloatField(),
"burrow": serializers.FloatField(),
# todo: model typed as any
"climb": serializers.StringRelatedField(),
# todo: model typed as any
"swim": serializers.StringRelatedField(),
"fly": serializers.IntegerField(allow_null=True),
"burrow": serializers.IntegerField(allow_null=True),
"climb": serializers.IntegerField(allow_null=True),
"swim": serializers.IntegerField(allow_null=True),
}
))
def get_speed_all(self):
Expand Down
17 changes: 6 additions & 11 deletions api_v2/serializers/creature.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,6 @@ class CreatureSerializer(GameContentSerializer):
initiative_bonus = serializers.SerializerMethodField()
illustration = ImageSummarySerializer()


class Meta:
'''Serializer meta options.'''
model = models.Creature
Expand Down Expand Up @@ -391,17 +390,13 @@ def get_speed(self, creature):
fields={
# todo: model typed as any
"unit": serializers.StringRelatedField(),
# todo: model typed as any
"walk": serializers.StringRelatedField(),
# todo: model typed as any
"crawl": serializers.StringRelatedField(),
"walk": serializers.IntegerField(),
"crawl": serializers.IntegerField(),
"hover": serializers.BooleanField(),
"fly": serializers.FloatField(),
"burrow": serializers.FloatField(),
# todo: model typed as any
"climb": serializers.StringRelatedField(),
# todo: model typed as any
"swim": serializers.StringRelatedField(),
"fly": serializers.IntegerField(allow_null=True),
"burrow": serializers.IntegerField(allow_null=True),
"climb": serializers.IntegerField(allow_null=True),
"swim": serializers.IntegerField(allow_null=True),
}
))
def get_speed_all(self, creature):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"long_range": null,
"name": "Bite attack",
"range": null,
"reach": 15.0,
"reach": 15,
"target_creature_only": false,
"to_hit_mod": 17
}
Expand Down Expand Up @@ -66,7 +66,7 @@
"long_range": null,
"name": "Claw attack",
"range": null,
"reach": 10.0,
"reach": 10,
"target_creature_only": false,
"to_hit_mod": 17
}
Expand Down Expand Up @@ -139,7 +139,7 @@
"long_range": null,
"name": "Tail attack",
"range": null,
"reach": 20.0,
"reach": 20,
"target_creature_only": false,
"to_hit_mod": 17
}
Expand Down Expand Up @@ -175,12 +175,12 @@
"alignment": "chaotic evil",
"armor_class": 22,
"armor_detail": "natural armor",
"blindsight_range": 60.0,
"blindsight_range": 60,
"category": "Monsters",
"challenge_rating_decimal": "24.000",
"challenge_rating_text": "24",
"creaturesets": [],
"darkvision_range": 120.0,
"darkvision_range": 120,
"document": {
"display_name": "5e 2014 Rules",
"gamesystem": {
Expand Down Expand Up @@ -242,7 +242,7 @@
"wisdom": 2
},
"name": "Ancient Red Dragon",
"normal_sight_range": 10560.0,
"normal_sight_range": 10560,
"passive_perception": 26,
"proficiency_bonus": null,
"resistances_and_immunities": {
Expand Down Expand Up @@ -305,20 +305,20 @@
"survival": 2
},
"speed": {
"climb": 40.0,
"fly": 80.0,
"climb": 40,
"fly": 80,
"unit": "feet",
"walk": 40.0
"walk": 40
},
"speed_all": {
"burrow": 0.0,
"climb": 40.0,
"crawl": 20.0,
"fly": 80.0,
"burrow": 0,
"climb": 40,
"crawl": 20,
"fly": 80,
"hover": false,
"swim": 20.0,
"swim": 20,
"unit": "feet",
"walk": 40.0
"walk": 40
},
"subcategory": "Dragons, Chromatic",
"traits": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"long_range": null,
"name": "Scimitar attack",
"range": null,
"reach": 5.0,
"reach": 5,
"target_creature_only": false,
"to_hit_mod": 4
}
Expand Down Expand Up @@ -59,9 +59,9 @@
"extra_damage_die_count": null,
"extra_damage_die_type": null,
"extra_damage_type": null,
"long_range": 320.0,
"long_range": 320,
"name": "Shortbow attack",
"range": 80.0,
"range": 80,
"reach": null,
"target_creature_only": false,
"to_hit_mod": 4
Expand All @@ -83,7 +83,7 @@
"challenge_rating_decimal": "0.250",
"challenge_rating_text": "1/4",
"creaturesets": [],
"darkvision_range": 60.0,
"darkvision_range": 60,
"document": {
"display_name": "5e 2014 Rules",
"gamesystem": {
Expand Down Expand Up @@ -200,7 +200,7 @@
"wisdom": -1
},
"name": "Goblin",
"normal_sight_range": 10560.0,
"normal_sight_range": 10560,
"passive_perception": 9,
"proficiency_bonus": null,
"resistances_and_immunities": {
Expand Down Expand Up @@ -252,17 +252,17 @@
},
"speed": {
"unit": "feet",
"walk": 30.0
"walk": 30
},
"speed_all": {
"burrow": 0.0,
"climb": 15.0,
"crawl": 15.0,
"fly": 0.0,
"burrow": 0,
"climb": 15,
"crawl": 15,
"fly": 0,
"hover": false,
"swim": 15.0,
"swim": 15,
"unit": "feet",
"walk": 30.0
"walk": 30
},
"subcategory": null,
"traits": [
Expand Down
Loading